Руководство по Ada (Ada 2022)
9.5.4 Управляющие операторы requeue
Оператор requeue_statement можно использовать для завершения оператора accept_statement или entry_body, при этом перенаправляя соответствующий вызов входа в новую (или ту же) очередь входов. Такое перенаправление может выполняться с разрешением или без разрешения промежуточной отмены вызова из-за прерывания или истечения срока ожидания.
Синтаксис
Правила разрешения имен
Имя procedure_or_entry_name оператора requeue_statement должно указывать на процедуру или вход (цель requeue). Профиль входа или профиль или профилированный профиль процедуры должен либо не иметь параметров, либо быть типа-совместимым (см. 6.3.1) с профилем внутреннего окружающего оператора entry_body или accept_statement.
Правила легитимности
Оператор requeue_statement должен находиться внутри вызываемого конструкта, который является либо оператором entry_body, либо оператором accept_statement, и этот конструкт должен быть внутренним окружающим телом или вызываемым конструктом.
Если целевой объект requeue имеет параметры, то его (профилированный) профиль должен быть подтипом, совместимым с профилем внутреннего окружающего вызываемого конструкта.
В случае оператора requeue_statement, где внутренний окружающий вызываемый конструкт предназначен для входа E1, для каждого выражения пост условия P1, применимого к E1, должно существовать выражение пост условия P2, применимое к цели requeue E2, такое что
- P1 полностью совместимо с выражением, полученным заменой каждого ссылочного элемента в P2 на формальный параметр E2 ссылочным элементом соответствующего формального параметра E1; и
- если P1 активен, то P2 также активен.
Целевая requeue не должна иметь применимого специфического или ширококлассового пост условия, включающего атрибут attribute_reference Old или Index.
Если целевой объект requeue объявлен непосредственно внутри определения задачи task_definition именованного типа задачи или определения защищенного типа protected_definition, и если оператор requeue находится внутри тела этого типа, и если requeue является внешним requeue, то целевой объект requeue не должен иметь специфического или ширококлассового пост условия, которое включает имя, обозначающее текущий экземпляр этого типа или любой сущности, объявленной в объявлении этого типа.
Если целевой объект является процедурой, то имя должно обозначать переименование входа или должно обозначать представление или профилированное представление примитивного подпрограммы синхронизированного интерфейса, где первый параметр непримитивного представления примитивной подпрограммы должен быть параметром управления, а аспект синхронизации должен быть указан с помощью synchronization_kind By_Entry для примитивной подпрограммы.
В операторе requeue_statement оператора accept_statement некоторой единицы задачи, либо целевой объект должен быть частью формального параметра оператора accept_statement, либо уровень доступности целевого объекта не должен быть равен или статически глубже любого окружающего оператора accept_statement единицы задачи. В операторе requeue_statement оператора entry_body некоторой защищенной единицы, либо целевой объект должен быть частью формального параметра оператора entry_body, либо уровень доступности целевого объекта не должен быть статически глубже уровня объявления входа entry_declaration для entry_body.
Динамические семантики
Выполнение оператора requeue_statement начинается со следующей последовательности шагов:
1.
Оценивается имя procedure_or_entry_name. Это включает оценку префикса (если есть) идентифицирующего целевую задачу или защищенный объект и выражения (если есть), идентифицирующего вход в группе входов.
2.
Если целевой объект не является частью формального параметра внутреннего окружающего вызываемого конструкта, выполняется проверка, что уровень доступности целевого объекта не равен или не глубже уровня внутреннего окружающего вызываемого конструкта. Если эта проверка не пройдена, генерируется ошибка Program_Error.
3.
Выполняются проверки пре условий, как при вызове целевого объекта requeue.
4.
Далее оператор entry_body или accept_statement, содержащий оператор requeue_statement завершается, завершается и покидается (см. 7.6.1).
При выполнении requeue для входа целевой задачи после выхода из окружающего вызываемого конструкта проверяется, открыт ли указанный вход, и вызов перенаправляется либо сразу, либо помещается в очередь, как при обычном вызове входа (см. 9.5.3).
При выполнении requeue для входа целевого защищенного объекта после выхода из окружающего вызываемого конструкта:
- если requeue является внутренним requeue (т.е., requeue возвращается в вход того же защищенного объекта — см. 9.5), вызов добавляется в очередь указанного входа, и текущее действие защищенного объекта продолжается (см. 9.5.1);
- если requeue является внешним requeue (т.е., целевой защищенный объект не является неявно тем же, что и текущий объект — см. 9.5), действие защищенного объекта запускается на целевом объекте и выполняется как при обычном вызове входа (см. 9.5.3).
Если целевой объект requeue, указанный в операторе requeue_statement, имеет формальные параметры, то во время выполнения оператора accept_statement или entry_body, соответствующих новому входу, и во время проверки любых условий предварительных для нового входа, формальные параметры обозначают те же объекты, что и соответствующие формальные параметры вызываемого конструкта, завершенного оператором requeue. В любом случае, параметры не указываются в операторе requeue_statement; передача параметров неявна.
Если оператор requeue_statement включает зарезервированные слова with abort (это requeue-with-abort), то:
- если исходный вызов входа был прерван (см. 9.8), то requeue действует как точка завершения прерывания для вызова, и вызов отменяется, и requeue не выполняется;
- если исходный вызов входа был ограничен во времени (или условный), то исходное время истечения срока действия является временем истечения срока действия для перенаправленного вызова.
Если зарезервированные слова with abort не указаны, то вызов остается защищенным от отмены, пока находится в очереди в результате оператора requeue_statement.
ПРИМЕЧАНИЕ. Перенаправление разрешено от одного входа к входу семейства входов или наоборот. Индекс входа, если он есть, не участвует в проверке соответствия подтипа между профилями двух входов; индекс входа является частью имени entry_name для входа семейства.
Примеры
Примеры операторов requeue:
requeue Request(Medium) with abort;
-- перенаправление на члена семейства входов текущей задачи, см. 9.1
-- перенаправление на члена семейства входов текущей задачи, см. 9.1
requeue Flags(I).Seize;
-- перенаправление на вход компонента массива, см. 9.4
-- перенаправление на вход компонента массива, см. 9.4