Руководство по Ada (Ada 2022)
9.7.4 Асинхронная передача управления
Асинхронный select_statement обеспечивает асинхронную передачу управления при завершении вызова входа или истечении срока действия задержки.
Синтаксис
Динамические семантика
При выполнении asynchronous_select, где triggering_statement является procedure_or_entry_call, имя entry_, имя procedure_ или префикс procedure_ и фактические параметры оцениваются так же, как и при простом вызове входа (см. 9.5.3) или вызове процедуры (см. 6.4). Если вызов является вызовом входа или вызовом процедуры, реализованной входом, вызов входа выполняется. Если вызов входа помещается в очередь (или помещается в очередь с прерыванием), то выполняется abortable_part. Если вызов входа выбран немедленно и никогда не помещается в очередь с прерыванием, то abortable_part никогда не запускается. Если вызов выполняется процедурой, которая не реализуется входом, вызов выполняется как описано в 6.4, а затем выполняется последовательность операторов sequence_of_statements в triggering_alternative; abortable_part никогда не запускается.
При выполнении asynchronous_select, где triggering_statement представляет собой delay_statement, выражение delay_expression оценивается, и время истечения срока определяется, как и для обычного delay_statement. Если время истечения срока еще не наступило, выполняется abortable_part.
Если abortable_part завершается и оставляет область до завершения triggering_statement, предпринимается попытка отменить triggering_statement. Если попытка отмены увенчалась успехом (см. 9.5.3 и 9.6), asynchronous_select завершается.
Если triggering_statement завершается не из-за отмены, abortable_part прерывается (если запущен, но еще не завершен — см. 9.8). Если triggering_statement завершается нормально, необязательная последовательность операторов sequence_of_statements альтернативы triggering_alternative выполняется после выхода из abortable_part.
Примеры
Пример цикла обработки основных команд для интерпретатора команд:
loop
select
Terminal.Wait_For_Interrupt;
Put_Line("Прервано");
then abort
-- Это будет прервано при прерывании терминала
Put_Line("-> ");
Get_Line(Command, Last);
Process_Command(Command(1..Last));
end select;
end loop;
select
Terminal.Wait_For_Interrupt;
Put_Line("Прервано");
then abort
-- Это будет прервано при прерывании терминала
Put_Line("-> ");
Get_Line(Command, Last);
Process_Command(Command(1..Last));
end select;
end loop;
Пример вычисления с ограничением по времени:
select
delay 5.0;
Put_Line("Вычисление не сходится");
then abort
-- Это вычисление должно завершиться в течение 5.0 секунд;
-- если нет, предполагается, что оно расходится.
Horribly_Complicated_Recursive_Function(X, Y);
end select;
delay 5.0;
Put_Line("Вычисление не сходится");
then abort
-- Это вычисление должно завершиться в течение 5.0 секунд;
-- если нет, предполагается, что оно расходится.
Horribly_Complicated_Recursive_Function(X, Y);
end select;
Обратите внимание, что эти примеры предполагают наличие точек завершения прерывания (см. 9.8) в выполнении abortable_part.