9.7.4 Asynchronous Transfer of Control
1
[An asynchronous select_statement
provides asynchronous transfer of control upon completion of an entry
call or the expiration of a delay.]
Syntax
2
asynchronous_select ::=
select
triggering_alternative
then abort
abortable_part
end select;
3
triggering_alternative ::= triggering_statement [
sequence_of_statements]
4/2
{
AI95-00345-01}
triggering_statement ::= procedure_or_entry_call entry_call_statement |
delay_statement
5
abortable_part ::= sequence_of_statements
Dynamic Semantics
6/2
{
AI95-00345-01}
{execution (asynchronous_select with
an entry call trigger) [partial]} {execution
(asynchronous_select with a procedure call trigger) [partial]}
For the execution of an
asynchronous_select
whose
triggering_statement is
a
procedure_or_entry_call an
entry_call_statement, the
entry_name,
procedure_name, or procedure_prefix,
and actual parameters are evaluated as for a simple entry call (see
9.5.3)
or procedure call (see 6.4). If the call is
an entry call or a call on a procedure implemented by an entry,,
and the entry call is issued. If the entry call is queued (or
requeued-with-abort), then the
abortable_part
is executed. [If the entry call is selected immediately, and never requeued-with-abort,
then the
abortable_part is never started.]
If the call is on a procedure that is not implemented by an entry, the
call proceeds as described in 6.4, followed
by the sequence_of_statements of the triggering_alternative[;
the abortable_part is never started].
7
{execution (asynchronous_select
with a delay_statement trigger) [partial]} For
the execution of an
asynchronous_select whose
triggering_statement is a
delay_statement,
the
delay_expression is evaluated and
the expiration time is determined, as for a normal
delay_statement.
If the expiration time has not already passed, the
abortable_part
is executed.
8
If the
abortable_part
completes and is left prior to completion of the
triggering_statement,
an attempt to cancel the
triggering_statement
is made. If the attempt to cancel succeeds (see
9.5.3
and
9.6), the
asynchronous_select
is complete.
9
If the
triggering_statement
completes other than due to cancellation, the
abortable_part
is aborted (if started but not yet completed — see
9.8).
If the
triggering_statement completes normally,
the optional
sequence_of_statements of the
triggering_alternative is executed after the
abortable_part is left.
9.a
Discussion: We currently don't specify
when the by-copy [in] out parameters are assigned back
into the actuals. We considered requiring that to happen after the abortable_part
is left. However, that doesn't seem useful enough to justify possibly
overspecifying the implementation approach, since some of the parameters
are passed by reference anyway.
9.b
In an earlier description, we required that
the sequence_of_statements of the triggering_alternative
execute after aborting the abortable_part,
but before waiting for it to complete and finalize, to provide more rapid
response to the triggering event in case the finalization was unbounded.
However, various reviewers felt that this created unnecessary complexity
in the description, and a potential for undesirable concurrency (and
nondeterminism) within a single task. We have now reverted to simpler,
more deterministic semantics, but anticipate that further discussion
of this issue might be appropriate during subsequent reviews. One possibility
is to leave this area implementation defined, so as to encourage experimentation.
The user would then have to assume the worst about what kinds of actions
are appropriate for the sequence_of_statements
of the triggering_alternative to achieve portability.
Examples
10
{signal
handling (example)} {interrupt
(example using asynchronous_select)} {terminal
interrupt (example)} Example of a main
command loop for a command interpreter:
11
loop
select
Terminal.Wait_For_Interrupt;
Put_Line("Interrupted");
then abort
-- This will be abandoned upon terminal interrupt
Put_Line("-> ");
Get_Line(Command, Last);
Process_Command(Command(1..Last));
end select;
end loop;
12
Example of a time-limited
calculation: {time-out: See asynchronous_select}
{time-out (example)}
{time limit (example)}
{interrupt (example
using asynchronous_select)} {timer
interrupt (example)}
13
select
delay 5.0;
Put_Line("Calculation does not converge");
then abort
-- This calculation should finish in 5.0 seconds;
-- if not, it is assumed to diverge.
Horribly_Complicated_Recursive_Function(X, Y);
end select;
Extensions to Ada 83
13.a
{
extensions to Ada 83}
Asynchronous_select
is new.
Extensions to Ada 95
13.b/2
{
AI95-00345-01}
{extensions to Ada 95} A
procedure can be used as the triggering_statement
of an asynchronous_select, if the procedure
might actually be an entry