Entry calls and accept statements are the primary means of synchronization of tasks, and of communicating values between tasks. An entry declaration is similar to a subprogram declaration and is only allowed in a task specification. The actions to be performed when an entry is called are specified by corresponding accept statements.
entry_declaration ::= entry identifier [(discrete_range)] [formal_part];
entry_call_statement ::= entry_name [actual_parameter_part];
accept_statement ::= accept entry_simple_name [(entry_index)] [formal_part] [do sequence_of_statements end [entry_simple_name]]; entry_index ::= expression
An entry declaration that includes a discrete range (see 3.6.1) declares a family of distinct entries having the same formal part (if any); that is, one such entry for each value of the discrete range. The term single entry is used in the definition of any rule that applies to any entry other than one of a family. The task designated by an object of a task type has (or owns) the entries declared in the specification of the task type.
Within the body of a task, each of its single entries or entry families can be named by the corresponding simple name. The name of an entry of a family takes the form of an indexed component, the family simple name being followed by the index in parentheses; the type of this index must be the same as that of the discrete range in the corresponding entry family declaration. Outside the body of a task an entry name has the form of a selected component, whose prefix denotes the task object, and whose selector is the simple name of one of its single entries or entry families.
A single entry overloads a subprogram, an enumeration literal, or another single entry if they have the same identifier. Overloading is not defined for entry families. A single entry or an entry of an entry family can be renamed as a procedure as explained in section 8.5.
The parameter modes defined for parameters of the formal part of an entry declaration are the same as for a subprogram declaration and have the same meaning (see 6.2). The syntax of an entry call statement is similar to that of a procedure call statement, and the rules for parameter associations are the same as for subprogram calls (see 6.4.1 and 6.4.2).
An accept statement specifies the actions to be performed at a call of a named entry (it can be an entry of a family). The formal part of an accept statement must conform to the formal part given in the declaration of the single entry or entry family named by the accept statement (see section 6.3.1 for the conformance rules). If a simple name appears at the end of an accept statement, it must repeat that given at the start.
An accept statement for an entry of a given task is only allowed within the corresponding task body; excluding within the body of any program unit that is, itself, inner to the task body; and excluding within another accept statement for either the same single entry or an entry of the same family. (One consequence of this rule is that a task can execute accept statements only for its own entries.) A task body can contain more than one accept statement for the same entry.
For the elaboration of an entry declaration, the discrete range, if any, is evaluated and the formal part, if any, is then elaborated as for a subprogram declaration.
Execution of an accept statement starts with the evaluation of the entry index (in the case of an entry of a family). Execution of an entry call statement starts with the evaluation of the entry name; this is followed by any evaluations required for actual parameters in the same manner as for a subprogram call (see 6.4). Further execution of an accept statement and of a corresponding entry call statement are synchronized.
If a given entry is called by only one task, there are two possibilities:
When an entry has been called and a corresponding accept statement has been reached, the sequence of statements, if any, of the accept statement is executed by the called task (while the calling task remains suspended). This interaction is called a rendezvous. Thereafter, the calling task and the task owning the entry continue their execution in parallel.
If several tasks call the same entry before a corresponding accept statement is reached, the calls are queued; there is one queue associated with each entry. Each execution of an accept statement removes one call from the queue. The calls are processed in the order of arrival.
An attempt to call an entry of a task that has completed its execution raises the exception TASKING_ERROR at the point of the call, in the calling task; similarly, this exception is raised at the point of the call if the called task completes its execution before accepting the call (see also 9.10 for the case when the called task becomes abnormal). The exception CONSTRAINT_ERROR is raised if the index of an entry of a family is not within the specified discrete range.
Examples of entry declarations:
entry READ(V : out ITEM); entry SEIZE; entry REQUEST(LEVEL)(D : ITEM); -- a family of entries
Examples of entry calls:
CONTROL.RELEASE; -- see 9.2 and 9.1 PRODUCER_CONSUMER.WRITE(E); -- see 9.1 POOL(5).READ(NEXT_CHAR); -- see 9.2 and 9.1 CONTROLLER.REQUEST(LOW)(SOME_ITEM); -- see 9.1
Examples of accept statements:
accept READ(V : out ITEM) do V := LOCAL_ITEM; end READ;
accept REQUEST(LOW)(D : ITEM) do ... end REQUEST;
The formal part given in an accept statement is not elaborated; it is only used to identify the corresponding entry.
An accept statement can call subprograms that issue entry calls. An accept statement need not have a sequence of statements even if the corresponding entry has parameters. Equally, it can have a sequence of statements even if the corresponding entry has no parameters. The sequence of statements of an accept statement can include return statements. A task can call its own entries but it will, of course, deadlock. The language permits conditional and timed entry calls (see 9.7.2 and 9.7.3). The language rules ensure that a task can only be in one entry queue at a given time.
If the bounds of the discrete range of an entry family are integer literals, the index (in an entry name or accept statement) must be of the predefined type INTEGER (see 3.6.1).
References: abnormal task, actual parameter part, completed task, conditional entry call, conformance rules, constraint_error exception, designate, discrete range, elaboration, and 3.9, enumeration literal, evaluation, expression, formal part, identifier, indexed component, integer type, name, object, overloading, and 8.7, parallel execution, prefix, procedure, procedure call, renaming declaration, return statement, scope, selected component, selector, sequence of statements, simple expression, simple name, subprogram, subprogram body, subprogram declaration, task, task body, task specification, tasking_error exception, timed entry call.