Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции - Часть 10.doc
Скачиваний:
36
Добавлен:
02.05.2014
Размер:
3.62 Mб
Скачать

10.3. Проектирование разъемов для межзадачных коммуникаций

Классы-разъемы инкапсулируют детали межзадачных коммуникаций, например сильно и слабо связанный обмен сообщениями. Сервисы для межзадачных коммуникаций и синхронизации может предоставлять многозадачное ядро. По­добные механизмы есть также в некоторых языках параллельного программиро­вания, в частности Ada или Java. Но ни один из этих языков не поддерживает сла­бо связанный обмен сообщениями. Чтобы реализовать указанную возможность, необходимо спроектировать скрывающий информацию класс MessageQueue, инкапсулирующий очередь сообщений и предоставляющий операции для досту­па к ней. Классы такого вида называются разъемами.

Ниже будут описаны три класса-разъема для реализации слабо связанного обмена сообщениями, сильно связанного обмена без ответа и сильно связанного обмена с ответом. Каждый разъем представляет собой монитор, одновременно обеспечивающий синхронизацию и скрывающий информацию о том, как это де­лается. В разъемах применяется синхронизация по условию. Такие мониторы могут использоваться как в однопроцессорной так и в многопро­цессорной системе с разделяемой памятью.

10.3.1. Проектирование разъема, реализующего очередь сообщений. Разъем, реализующий очередь сообщений, используется для инкапсуляции ме­ханизма слабо связанного обмена сообщениями. Это монитор, инкапсулирующий очередь, которая обычно существует в виде связанного списка. Разъем предостав­ляет синхронизированные операции send для отправки сообщения (вызывается за­дачей-производителем) и receive для получения сообщения (вызывается зада­чей-получателем) – рис.10.4. Производитель приостанавливается, если очередь заполнена (messageCount = maxCount) и возобновляет работу, когда освобож­дается место для размещения нового сообщения. Поместив сообщение в очередь, производитель продолжает работать и в состоянии посылать новые сообщения. Потребитель приостанавливается, когда очередь пуста (messageCount = 0) и ак­тивизируется, как только в очередь поступит сообщение. Потребитель не при­останавливается, если в очереди есть сообщения. Предполагается, что может быть несколько производителей и один потребитель.

Рис. 10.4. Пример разъема для реализации очереди сообщений

monitor MessageQueue

-- Инкапсулирует очередь сообщений,

-- рассчитанную максимум на maxCount

-- сообщений. Операции монитора выполняются

-- взаимно исключающим образом.

private maxCount : Integer;

private messageCount : Integer = 0;

public send (in message)

while messageCount = maxCount do wait;

Поместить сообщение в очередь;

Увеличить messageCount;

if messageCount = 1 then signal;

end send;

public receive (out message)

while messageCount = 0 do wait;

Извлечь сообщение из очереди;

Уменьшить messageCount;

if messageCount = maxCount - 1 then signal;

end receive;

end MessageQueue;

10.3.2. Проектирование разъема, реализующего буфер сообщений. Разъем, реализующий буфер сообщений, используется для инкапсуляции ме­ханизма сильно связанного обмена сообщениями без ответа. Это монитор, инкап­сулирующий буфер на одно сообщение. Разъем предоставляет синхронизирован­ные операции для отправки и получения сообщений (рис. 10.5). Производитель вызывает операцию send, а потребитель – операцию receive. Производитель приостанавливается, если буфер заполнен. Поместив сообщение в буфер, произ­водитель ждет, пока потребитель примет его. Потребитель приостанавливается, когда буфер пуст. Предполагается, что может быть несколько производителей и один потребитель.

monitor MessageBuffer

-- Инкапсулирует буфер сообщений, в котором

-- может находиться не более одного

-- сообщения. Операции монитора выполняются

-- взаимно исключающим образом.

private messageBufferFull : Boolean = false;

private messageCount : Integer = 0;

public send (in message)

Поместить сообщение в буфер;

messageBufferFull = true;

signal;

while messageBufferFull = true do wait;

end send;

public receive (out message)

while messageBufferFull = false do wait;

Извлечь сообщение из буфера;

messageBufferFull = false;

signal;

end receive;

end MessageBuffer;

Рис. 10.5. Пример разъема для реализации буфера сообщений

10.3.3. Проектирование разъема, реализующего буфер сообщений с ответом. Разъем, реализующий буфер сообщений с ответом, используется для инкапсу­ляции механизма сильно связанного обмена сообщениями с ответом. Это монитор, инкапсулирующий буфер на одно сообщение и буфер на один ответ. Разъем предо­ставляет синхронизированные операции для отправки и получения сообщений, а также для отправки ответа (рис.10.6). Производитель вызывает операцию send для пересылки сообщения, а потребитель – операцию receive для приема сооб­щения и операцию reply для отправки ответа. Поместив сообщение в буфер, производитель ждет ответа от потребителя. Потребитель приостанавливается, когда буфер пуст. Предполагается, что может быть несколько производителей и один потребитель.

monitor MessageBuffer&Response

-- Инкапсулирует буфер сообщений, в котором

-- может находиться не более одного

-- сообщения, и буфер, в котором может

-- находиться не более одного ответа.

-- Операции монитора выполняются взаимно

-- исключающим образом.

private messageBufferFull : Boolean = false;

private responseBufferFull : Boolean = false;

private messageCount : Integer = 0;

public send (in message)

Поместить сообщение в буфер;

messageBufferFull = true;

signal ;

while responseBufferFull = false do wait;

Извлечь ответ из буфера;

responseBufferFull = false;

end send;

public receive (out message)

while messageBufferFull = false do wait;

Извлечь сообщение из буфера;

messageBufferFull = false;

end receive;

public reply (in response)

Поместить ответ в буфер;

responseBufferFull = true;

signal ;

end reply;

end MessageBuffer&Response

Рис.10.6. Пример разъема для реализации буфера сообщений с ответом

10.3.4. Проектирование кооперативных задач с использованием разъемов. Теперь рассмотрим проектирование группы кооперативных задач, общающих­ся между собой с помощью объектов-разъемов. Для иллюстрации воспользуемся примером из подсистемы Банкомат. Разъемы для этой подсистемы изображены на рис.10.7; есть два разъема – очереди сообщений и один разъем – буфер сообщений.

Объект Очередь Сообщений Управления Банкоматом инкапсулирует оче­редь входных сообщений задачи Контроллер Банкомата, для которой есть не­сколько производителей. Объект Очередь Сообщений Приглашений инкапсу­лирует очередь сообщений, посылаемых задачей Контроллер Банкомата задаче Интерфейс Клиента. И в том, и в другом случае производитель вызывает опера­цию send объекта-разъема, а потребитель – операцию receive того же объекта. Имеется также разъем буфер Сообщений Устройства Считывания, который инкапсулирует синхронный обмен без ответа между задачами Контроллер Бан­комата и Интерфейс Устройства Считывания Карточек.

Наконец, есть объект заместитель Банковского Сервера. Он скрывает де­тали коммуникации с удаленным Банковским Сервером, применяя синхронный обмен сообщениями без ответа. Например, в языке Java этот заместитель восполь­зовался бы механизмом вызова удаленных методов (RMI), описанным ранее.

Рис.10.7. Пример кооперативных задач, использующих разъемы