Основы объектно-ориентированного проектирования


Резервирование объекта - часть 2


Наше соглашение состоит в том, что, если a -это непустое сепаратное выражение, то вызов вида:

действия_требующие_исключительного_доступа (a)

автоматически заставляет ожидать до тех пор, пока объект, присоединенный к a, не станет доступным. В инструкции hold нет никакой необходимости - для резервирования сепаратного объекта достаточно указать его в качестве фактического аргумента вызова.

Заметим, что ожидание имеет смысл, только если подпрограмма содержит хоть один вызов x.some_routine с формальным аргументом x, соответствующим a. В противном случае, например, если она выполняет только присваивание вида some_attribute := x, ждать нет никакой необходимости. Это будет уточнено в полной форме правила, которое будет сформулировано далее в этой лекции.

Возможны и другие подходы, в которых авторы предлагают сохранить инструкцию hold. Но передача аргумента в качестве механизма резервирования объекта сохраняет простоту и легкость освоения модели параллелизма. Схема с hold привлекательна для разработчиков, поскольку соответствует девизу ОО-разработки "Инкапсулировать повторения", а главное, объединяет в одной подпрограмме действия, требующие исключающего доступа к объекту. Поскольку этой подпрограмме неизбежно потребуется аргумент, представляющий сам объект, то мы пошли дальше и считаем наличие такого аргумента достаточным для обеспечения резервирования объекта без введения ключевого слова hold.

Это соглашение также означает, что (достаточно парадоксально) большинство сепаратных вызовов не должно ждать. Выполняя тело подпрограммы с сепаратным формальным аргументом a, мы уже зарезервировали соответствующий присоединенный объект, поэтому всякий вызов с целью a может исполняться немедленно. Как уже отмечено, не требуется ждать, когда он завершится. В общем случае для подпрограммы вида:

r (a: separate SOME_TYPE) is do ...; a.r1 (...); ... ...; a.r2 (...); ... end

реализация может продолжать выполнение остальных инструкций, не дожидаясь завершения любого из двух вызовов при условии, что она протоколирует вызовы для a так, что они будут выполняться в требуемом порядке. (Нам еще нужно понять, как, если это потребуется, ждать завершения сепаратного вызова; пока же, мы просто запускаем вызовы и никогда не ждем!)

Если у подпрограммы имеется несколько сепаратных аргументов, то вызов клиента будет ждать, пока не сможет зарезервировать все соответствующие объекты. Это требование тяжело реализовать при компиляции, которая должна порождать код, используя протоколы для множественного одновременного резервирования. По этой причине компилятор мог бы требовать, чтобы подпрограмма использовала не более одного сепаратного формального аргумента. Но при полной реализации предложенного механизма разработчики приложений получают значительные удобства; в частности, рассматриваемая в качестве типичного примера далее в этой лекции знаменитая проблема "обедающих философов" допускает почти тривиальное решение.




Начало  Назад  Вперед



Книжный магазин