Справочник Ada 2012
9.7.4 Асинхронная передача управления
Асинхронное select_statement обеспечивает асинхронную передачу управления при завершении вызова входа или истечении задержки.
Синтаксис
Динамическая семантика
При выполнении asynchronous_select, где triggering_statement представляет собой procedure_or_entry_call, имя_входа, имя_процедуры или префикс_процедуры, а также фактические параметры оцениваются так же, как при простом вызове входа (см. 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;
Обратите внимание, что эти примеры предполагают, что есть точки завершения отмены в выполнении abortable_part.