Устранение блокировок (тупиков)
Наряду с несколькими важными примерами передачи сепаратных ссылок в сепаратные вызовы, мы видели, что возможна также передача несепаратных ссылок при условии, что соответствующие формальные аргументы объявлены как сепаратные (поскольку на стороне поставщика они представляют чужие объекты и нам не нужны предатели). Несепаратные ссылки увеличивают риск блокировок, и с ними нужно обходиться аккуратно.
Обычный способ передачи несепаратных ссылок состоит в использовании схемы визитной карточки: используется сепаратный вызов вида x.f (a) , где x - сепаратная сущность, а a - нет; иначе говоря, a - это ссылка на локальный объект клиента, возможно, на сам Current. На стороне поставщика f имеет вид:
f (u: separate SOME_TYPE) is do local_reference := u endгде local_reference типа separate SOME_TYPE является атрибутом объемлющего класса поставщика. Далее поставщик может использовать local_reference в подпрограммах, отличных от f, для выполнения операций над объектами на стороне клиента с помощью вызовов вида local_reference.some_routine (...).
Эта схема корректна. Предположим, однако, что f делает еще что-то, например, включает для некоторого g вызов вида u.g (...). Это с большой вероятностью приведет к тупику: клиент (обработчик объекта, присоединенного к u и a) занят выполнением f или, быть может, ожиданием по необходимости выполнения другого вызова, резервирующего тот же объект.
Следующее правило позволяет избежать таких ситуаций:
Принцип визитной карточки Если сепаратный вызов использует несепаратный фактический аргумент типа ссылки, то соответствующий формальный аргумент должен использоваться в подпрограмме только в качестве источника присваиваний. |
Пока это только методологическое руководящее указание, хотя было бы желательно ввести соответствующее формальное правило (в упражнениях У12.4 и У12.13 эта идея рассматривается глубже). Дополнительные комментарии о блокировках появятся еще при общем обсуждении.