Справочник Ada 95
9.5.3 Вызовы входов
Оператор entry_call_statement (вызов входа) может встречаться в различных контекстах. Простой вызов входа — это автономный оператор, представляющий собой безусловный вызов входа целевой задачи или защищенного объекта. Вызовы входов также могут быть частью операторов select_statement (см. 9.7).
Синтаксис
entry_call_statement ::= имя_входа [actual_parameter_part];
Правила разрешения имен
Указанное в операторе entry_call_statement имя_входа должно быть именем входа. Правила сопоставления параметров такие же, как и для вызовов подпрограмм (см. 6.4 и 6.4.1).
Статическая семантика
Имя_входа оператора entry_call_statement указывает (явным или неявным образом) целевой объект вызова, вход или семейство входов, а также индекс входа, если он есть (см. 9.5).
Динамическая семантика
В определенных условиях (подробно описанных ниже) вход задачи или защищенного объекта проверяется на предмет того, является ли он открытым или закрытым:
- Вход задачи открыт, если задача заблокирована на операторе accept_statement, соответствующем входу (см. 9.5.2), или на selective_accept (см. 9.7.1) с открытым accept_alternative, соответствующим входу; в противном случае он закрыт.
- Вход защищенного объекта открыт, если условие entry_barrier соответствующего entry_body имеет значение True; в противном случае он закрыт. Если при оценке condition возникает исключение, исключение Program_Error передается всем текущим вызывающим сторонам всех входов защищенного объекта.
Для выполнения оператора entry_call_statement оценка имени и сопоставлений параметров выполняется так же, как и для вызова подпрограммы (см. 6.4). Затем вызов входа выдается: при вызове входа защищенного объекта запускается новое защищенное действие на объекте (см. 9.5.1). Проверяется, открыт ли именованный вход; если открыт, вызов входа считается немедленно выбранным, и выполнение вызова продолжается следующим образом:
- Для вызова открытого входа задачи принимающая задача становится готовой и продолжает выполнение соответствующего оператора accept_statement (см. 9.5.2).
- Для вызова открытого входа защищенного объекта соответствующий entry_body выполняется (см. 9.5.2) как часть защищенного действия.
Если оператор accept_statement или entry_body завершается иначе, чем с помощью requeue (см. 9.5.4), выполняется возврат к вызывающей стороне (после обработки очередей входов — см. ниже); любые необходимые задания формальных параметров фактическим параметрам происходят, как при вызове подпрограммы (см. 6.4.1); такие задания выполняются вне любого защищенного действия.
Если именованный вход закрыт, вызов входа добавляется в очередь входа (в рамках защищенного действия для вызова защищенного входа) и остается в очереди до тех пор, пока не будет выбран или отменен; для каждого входа заданной задачи или защищенного объекта (включая каждый вход семейства входов) существует отдельная (логическая) очередь входов.
Когда выбран вызов в очереди, он удаляется из очереди входа. Выбор вызова из очереди входа конкретного входа называется обслуживанием очереди входа.
- Когда связанная задача достигает соответствующего оператора accept_statement или selective_accept с соответствующим открытым accept_alternative;
- Если после выполнения, как части защищенного действия на связанном защищенном объекте, операции над объектом, отличной от вызова защищенной функции, вход проверяется и оказывается открытым.
Если в очереди есть хотя бы один вызов открытого входа, один такой вызов выбирается в соответствии с действующей политикой очереди входов (см. ниже), и соответствующий оператор accept_statement или entry_body выполняется так же, как и для вызова входа, который выбран немедленно.
Политика очереди входов управляет выбором среди очередей вызовов как для задач, так и для защищенных входов. По умолчанию политика очереди входов заключается в выборе вызовов в заданной очереди в порядке их поступления. Если вызовы из двух или более очередей одновременно подходят для выбора, политика очереди входов по умолчанию не определяет, какая очередь обслуживается первой. Другие политики очереди входов могут быть заданы с помощью pragma (см. D.4).
Для защищенного объекта указанное обслуживание очередей входов продолжается до тех пор, пока не останется открытых входов с очередями вызовов, после чего защищенное действие завершается.
Для вызова входа, который добавлен в очередь и который не является triggering_statement asynchronous_select (см. 9.7.4), вызывающая задача блокируется до тех пор, пока вызов не будет отменен или не будет выбран, и соответствующий accept_statement или entry_body завершит работу без переочереденности. Кроме того, вызывающая задача блокируется во время согласования.
Можно попытаться отменить вызов входа при прерывании (см. 9.8) и как часть определенных форм select_statement (см. 9.7.2, 9.7.3 и 9.7.4). Отмена не происходит до момента (если таковой имеется), когда вызов находится в какой-то очереди входов, и не защищен от отмены в рамках requeue (см. 9.5.4); в такой момент вызов удаляется из очереди входа и завершается из-за отмены. Отмена вызова входа защищенного объекта — это защищенное действие, и как таковое оно не может происходить, когда происходит любое другое защищенное действие над защищенным объектом. Как и любое защищенное действие, оно включает обработку очередей входов (в случае, если какой-либо барьер входа зависит от атрибута Count).
Вызов входа задачи, которая уже завершила свою работу, вызывает исключение Tasking_Error в момент вызова; аналогичным образом это исключение возникает в момент вызова, если вызываемая задача завершает свою работу или становится аномальной до принятия вызова или завершения согласования (см. 9.8). Это относится как к простому вызову входа, так и к вызову входа в рамках select_statement.
Разрешения для реализации
Реализация может выполнять последовательность шагов защищенного действия с использованием любого потока управления; это не обязательно должен быть поток управления задачи, которая запустила защищенное действие. Если entry_body завершается без переочереденности, соответствующая вызывающая задача может быть подготовлена к работе без ожидания завершения всего защищенного действия.
При проверке входа защищенного объекта на предмет его открытости реализация не обязана повторно оценивать condition соответствующего entry_barrier, если ни одна переменная или атрибут, на которые ссылается condition (прямо или косвенно), не были изменены выполнением (или отмененой) защищенной процедуры или вызова входа на объекте с момента последней оценки condition.
Реализация может оценивать condition всех entry_barrier данного защищенного объекта всякий раз, когда любой вход объекта проверяется на открытость.
При попытке отмены вызова входа реализация не обязана пытаться это сделать с использованием потока управления задачи (или прерывания), которая инициировала отмену; в частности, она может использовать поток управления вызывающей стороной для попытки отмены, даже если это может привести к выбору вызова входа в промежутке.
ПРИМЕЧАНИЯ
26 Если во время выполнения entry_body возникает исключение, оно передаётся соответствующей вызывающей стороне (см. 11.4).
27 Для вызова защищенного входа вход проверяется на открытость перед добавлением вызова в очередь и повторно, если его атрибут Count (см. 9.9) используется в каком-либо барьере входа.
28 Помимо простых вызовов входа, язык допускает временные, условные и асинхронные вызовы входа (см. 9.7.2, 9.7.3 и см. 9.7.4).
29 Условие entry_barrier разрешено реализовывать чаще, чем строго необходимо, даже если оценка может иметь побочные эффекты. С другой стороны, реализация не должна переоценивать условие, если ничего, что оно ссылается, не было обновлено вмешающимся защищённым действием над защищённым объектом, даже если условие ссылается на какую-либо глобальную переменную, которая могла быть обновлена действием, выполненным вне защищённого действия.
Примеры
Примеры вызовов входа:
Agent.Shut_Down; -- см. 9.1
Parser.Next_Lexeme(E); -- см. 9.1
Pool(5).Read(Next_Char); -- см. 9.1
Controller.Request(Low)(Some_Item); -- см. 9.1
Flags(3).Seize; -- см. 9.4
Parser.Next_Lexeme(E); -- см. 9.1
Pool(5).Read(Next_Char); -- см. 9.1
Controller.Request(Low)(Some_Item); -- см. 9.1
Flags(3).Seize; -- см. 9.4