9.7.4 Asynchronous Transfer of Control
[An asynchronous
select_statement
provides asynchronous transfer of control upon completion of an entry
call or the expiration of a delay.]
Syntax
Dynamic Semantics
{
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,
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, 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].
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.
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
{signal
handling (example)} {interrupt
(example using asynchronous_select)} {terminal
interrupt (example)} Example of a main
command loop for a command interpreter:
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;
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)}
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
Extensions to Ada 95