Справочник Ada 95
9.7.4 Асинхронный перевод управления
Асинхронное select_statement обеспечивает асинхронный перевод управления при завершении вызова входа или истечении срока действия задержки.
Синтаксис
asynchronous_select ::=
select
triggering_alternative
then abort
abortable_part
end select;
select
triggering_alternative
then abort
abortable_part
end select;
triggering_alternative ::= triggering_statement [sequence_of_statements]
triggering_statement ::= entry_call_statement | delay_statement
abortable_part ::= sequence_of_statements
Динамические семантика
Для выполнения asynchronous_select, у которого triggering_statement является entry_call_statement, имя входа и фактические параметры вычисляются так же, как для простого вызова входа (см. 9.5.3), и вызов входа выполняется. Если вызов входа помещается в очередь (или повторно помещается в очередь с отменой), выполняется abortable_part. Если вызов входа выбирается немедленно и никогда не повторно помещается в очередь с отменой, то abortable_part никогда не запускается.
Для выполнения asynchronous_select, у которого triggering_statement является delay_statement, выражение задержки вычисляется и определяется время истечения срока действия, как и для обычного 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;