There are three forms of select statements. One form provides a selective wait for one or more alternatives. The other two provide conditional and timed entry calls.
select_statement ::= selective_wait | conditional_entry_call | timed_entry_call
References: selective wait, conditional entry call, timed entry call.
Rationale references: 13.2.5 The Select Statement, 13.2.6 Timing, 13.2.7 Timed and Conditional Communication
Style Guide references: 2.1.2 Indentation, 5.6.1 Nesting, 6.2.1 Efficient Task Communications, 6.2.6 Communication Complexity
Sub-topics:
This form of the select statement allows a combination of waiting for, and selecting from, one or more alternatives. The selection can depend on conditions associated with each alternative of the selective wait.
selective_wait ::= select select_alternative {or select_alternative} [else sequence_of_statements] end select; select_alternative ::= [when condition =>] selective_wait_alternative selective_wait_alternative ::= accept_alternative | delay_alternative | terminate_alternative accept_alternative ::= accept_statement [sequence_of_statements] delay_alternative ::= delay_statement [sequence_of_statements] terminate_alternative ::= terminate;
A selective wait must contain at least one accept alternative. In addition a selective wait can contain either a terminate alternative (only one), or one or more delay alternatives, or an else part; these three possibilities are mutually exclusive.
A select alternative is said to be open if it does not start with when and a condition, or if the condition is TRUE. It is said to be closed otherwise.
For the execution of a selective wait, any conditions specified after when are evaluated in some order that is not defined by the language; open alternatives are thus determined. For an open delay alternative, the delay expression is also evaluated. Similarly, for an open accept alternative for an entry of a family, the entry index is also evaluated. Selection and execution of one open alternative, or of the else part, then completes the execution of the selective wait; the rules for this selection are described below.
Open accept alternatives are first considered. Selection of one such alternative takes place immediately if a corresponding rendezvous is possible, that is, if there is a corresponding entry call issued by another task and waiting to be accepted. If several alternatives can thus be selected, one of them is selected arbitrarily (that is, the language does not define which one). When such an alternative is selected, the corresponding accept statement and possible subsequent statements are executed. If no rendezvous is immediately possible and there is no else part, the task waits until an open selective wait alternative can be selected.
Selection of the other forms of alternative or of an else part is performed as follows:
The exception PROGRAM_ERROR is raised if all alternatives are closed and there is no else part.
Examples of a select statement:
select accept DRIVER_AWAKE_SIGNAL; or delay 30.0*SECONDS; STOP_THE_TRAIN; end select;
Example of a task body with a select statement:
task body RESOURCE is BUSY : BOOLEAN := FALSE; begin loop select when not BUSY => accept SEIZE do BUSY := TRUE; end; or accept RELEASE do BUSY := FALSE; end; or terminate; end select; end loop; end RESOURCE;
Notes:
A selective wait is allowed to have several open delay alternatives. A selective wait is allowed to have several open accept alternatives for the same entry.
References: accept statement, condition, declaration, delay expression, delay statement, duration, entry, entry call, entry index, program_error exception, queued entry call, rendezvous, select statement, sequence of statements, task.
Style Guide references: 6.2.1 Efficient Task Communications, 6.2.2 Defensive Task Communication, 6.2.4 Shared Variables, 6.2.5 Tentative Rendezvous Constructs, 6.3.2 Normal Termination, 7.4.4 Select Statement Evaluation Order
A conditional entry call issues an entry call that is then canceled if a rendezvous is not immediately possible.
conditional_entry_call ::= select entry_call_statement [sequence_of_statements] else sequence_of_statements end select;
For the execution of a conditional entry call, the entry name is first evaluated. This is followed by any evaluations required for actual parameters as in the case of a subprogram call (see 6.4).
The entry call is canceled if the execution of the called task has not reached a point where it is ready to accept the call (that is, either an accept statement for the corresponding entry, or a select statement with an open accept alternative for the entry), or if there are prior queued entry calls for this entry. If the called task has reached a select statement, the entry call is canceled if an accept alternative for this entry is not selected.
If the entry call is canceled, the statements of the else part are executed. Otherwise, the rendezvous takes place; and the optional sequence of statements after the entry call is then executed.
The execution of a conditional entry call raises the exception TASKING_ERROR if the called task has already completed its execution (see also 9.10 for the case when the called task becomes abnormal).
Example:
procedure SPIN(R : RESOURCE) is begin loop select R.SEIZE; return; else null; -- busy waiting end select; end loop; end;
References: abnormal task, accept statement, actual parameter part, completed task, entry call statement, entry family, entry index, evaluation, expression, open alternative, queued entry call, rendezvous, select statement, sequence of statements, task, tasking_error exception.
Style Guide references: 4.2.4 Hiding Tasks, 6.2.5 Tentative Rendezvous Constructs
A timed entry call issues an entry call that is canceled if a rendezvous is not started within a given delay.
timed_entry_call ::= select entry_call_statement [sequence_of_statements] or delay_alternative end select;
For the execution of a timed entry call, the entry name is first evaluated. This is followed by any evaluations required for actual parameters as in the case of a subprogram call (see 6.4). The expression stating the delay is then evaluated, and the entry call is finally issued.
If a rendezvous can be started within the specified duration (or immediately, as for a conditional entry call, for a negative or zero delay), it is performed and the optional sequence of statements after the entry call is then executed. Otherwise, the entry call is canceled when the specified duration has expired, and the optional sequence of statements of the delay alternative is executed.
The execution of a timed entry call raises the exception TASKING_ERROR if the called task completes its execution before accepting the call (see also 9.10 for the case when the called task becomes abnormal).
Example:
select CONTROLLER.REQUEST(MEDIUM)(SOME_ITEM); or delay 45.0; -- controller too busy, try something else end select;
References: abnormal task, accept statement, actual parameter part, completed task, conditional entry call, delay expression, delay statement, duration, entry call statement, entry family, entry index, evaluation, expression, rendezvous, sequence of statements, task, tasking_error exception.
Style Guide references: 4.2.4 Hiding Tasks, 6.1.5 Delay Statements, 6.2.5 Tentative Rendezvous Constructs
Address any questions or comments to adainfo@sw-eng.falls-church.va.us.