Spec-Zone.ru › Ada 2022
Руководство по Ada (Ada 2022)

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; в противном случае, она закрыта. Если при вычислении условия возникает исключение, исключение Program_Error передаётся всем текущим вызывающим сторонам всех записей защищённого объекта.
При выполнении оператора вызова записи (entry_call_statement), вычисляются имя и ассоциации параметров, как и при вызове подпрограммы (см. 6.4). Затем вызов записи формируется: для вызова записи защищённого объекта запускается новое защищённое действие в объекте (см. 9.5.1). Проверяется, открыта ли указанная запись; если открыта, вызов записи считается выбранным немедленно, и выполнение вызова продолжается следующим образом:
  • Для вызова открытой записи задачи принимающая задача становится готовой и продолжает выполнение соответствующего оператора accept_statement (см. 9.5.2).
  • Для вызова открытой записи защищённого объекта выполняется соответствующий оператор entry_body (см. 9.5.2) в рамках защищённого действия.
Если оператор accept_statement или entry_body завершается не переочереднением (см. 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). Отмена не происходит до тех пор, пока вызов не окажется в очереди записей и не защищён от отмены в рамках переочередяния (см. 9.5.4); в такой момент вызов удаляется из очереди записей, и вызов завершается из-за отмены. Отмена вызова записи защищённого объекта является защищённым действием и, как таковое, не может произойти, пока выполняется любое другое защищённое действие над защищённым объектом. Как и любое защищённое действие, оно включает обслуживание очередей записей (в случае, если какой-либо барьер записи зависит от атрибута Count).
Вызов записи задачи, которая уже завершила своё выполнение, вызывает исключение Tasking_Error в точке вызова; аналогично, это исключение возникает в точке вызова, если вызываемая задача завершает выполнение или становится аномальной до принятия вызова или завершения встречи (см. 9.8). Это относится как к простому вызову записи, так и к вызову записи в составе оператора select_statement.

Разрешения реализации

Реализация может выполнить последовательность шагов защищённого действия, используя любой поток управления; это может быть поток, отличный от потока задачи, которая запустила защищённое действие. Если оператор entry_body завершается без переочередяния, то соответствующая вызывающая задача может быть подготовлена к работе без ожидания завершения всего защищённого действия.
Когда проверяется, открыта ли запись защищённого объекта, реализация может обойти повторное вычисление условия соответствующего entry_barrier, если ни одна переменная или атрибут, на которые ссылается условие (непосредственно или косвенно), не была изменена выполнением (или отмененой) вызова эксклюзивной защищённой операции объекта с момента последнего вычисления условия.
END_OF_DOCUMENT_MARKER
Реализация может оценивать условие всех барьеров_входа данного защищённого объекта в любой момент проверки открытия любого входа объекта.
При попытке отменить вызов входа, реализация может использовать поток управления, отличный от потока задачи (или прерывания), инициировавшего отмену; в частности, она может использовать поток управления вызывающего объекта для попытки отмены, даже если это может позволить выбрать вызов входа в промежутке.
ПРИМЕЧАНИЕ 1 Если во время выполнения тела_входа возникает исключение, оно передаётся соответствующему вызывающему объекту (см. 11.4).
ПРИМЕЧАНИЕ 2 Для вызова защищённого входа вход проверяется на открытость перед добавлением вызова в очередь, а затем ещё раз, если его атрибут Count (см. 9.9) используется в каком-либо барьере входа.
ПРИМЕЧАНИЕ 3 Помимо простых вызовов входа, язык допускает временные, условные и асинхронные вызовы входа (см. 9.7.2, 9.7.3 и 9.7.4).
ПРИМЕЧАНИЕ 4 Реализация может оценивать условие барьера_входа чаще, чем это строго необходимо, даже если оценка может иметь побочные эффекты. С другой стороны, реализация может избежать повторной оценки условия, если ничего, к чему оно ссылается, не было обновлено промежуточным защищённым действием над защищённым объектом, даже если условие ссылается на какую-либо глобальную переменную, обновлённую действием, выполняемым вне защищённого действия.

Примеры

Примеры вызовов входа:
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


Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API