Contents Index Previous Next
9.5.2 Entries and Accept Statements
1
Entry_declarations,
with the corresponding entry_bodies
or accept_statements, are used to
define potentially queued operations on tasks and protected objects.
Syntax
2
entry_declaration
::=
entry defining_identifier [(
discrete_subtype_definition)]
parameter_profile;
3
accept_statement
::=
accept entry_direct_name [(
entry_index)]
parameter_profile [
do
handled_sequence_of_statements
end [
entry_identifier]];
3.a
Reason: We cannot use defining_identifier
for accept_statements. Although
an accept_statement is sort of like
a body, it can appear nested within a block_statement,
and therefore be hidden from its own entry by an outer homograph.
4
entry_index
::= expression
5
entry_body
::=
entry defining_identifier entry_body_formal_part entry_barrier is
declarative_part
begin
handled_sequence_of_statements
end [
entry_identifier];
6
entry_body_formal_part
::= [(
entry_index_specification)]
parameter_profile
7
entry_barrier
::= when condition
8
entry_index_specification
::= for defining_identifier in discrete_subtype_definition
9
If an entry_identifier
appears at the end of an accept_statement,
it shall repeat the entry_direct_name.
If an entry_identifier appears
at the end of an entry_body, it
shall repeat the defining_identifier.
10
[An entry_declaration
is allowed only in a protected or task declaration.]
10.a
Proof: This follows from
the BNF.
Name Resolution Rules
11
{expected profile (accept_statement
entry_direct_name) [partial]} In an
accept_statement,
the expected profile for the
entry_direct_name
is that of the
entry_declaration;
{expected type (entry_index) [partial]} the
expected type for an
entry_index
is that of the subtype defined by the
discrete_subtype_definition
of the corresponding
entry_declaration.
12
Within the
handled_sequence_of_statements
of an
accept_statement, if a
selected_component
has a
prefix that denotes the corresponding
entry_declaration, then the entity denoted
by the
prefix is the
accept_statement,
and the
selected_component is interpreted
as an expanded name (see
4.1.3)[; the
selector_name
of the
selected_component has to be the
identifier for some formal parameter of
the
accept_statement].
12.a
Proof: The only declarations
that occur immediately within the declarative region of an accept_statement
are those for its formal parameters.
Legality Rules
13
An
entry_declaration
in a task declaration shall not contain a specification for an access parameter
(see
3.10).
13.a
Reason:
Access parameters for task entries would require a complex implementation.
For example:
13.b
task T is
entry E(Z : access Integer); -- Illegal!
end T;
13.c
task body T is
begin
declare
type A is access all Integer;
X : A;
Int : aliased Integer;
task Inner;
task body Inner is
begin
T.E(Int'Access);
end Inner;
begin
accept E(Z : access Integer) do
X := A(Z); -- Accessibility_Check
end E;
end;
end T;
13.d
Implementing the Accessibility_Check
inside the accept_statement for
E is difficult, since one does not know whether the entry caller is calling
from inside the immediately enclosing declare block or from outside it.
This means that the lexical nesting level associated with the designated
object is not sufficient to determine whether the Accessibility_Check
should pass or fail.
13.e
Note that such problems do not
arise with protected entries, because entry_bodies
are always nested immediately within the protected_body;
they cannot be further nested as can accept_statements,
nor can they be called from within the protected_body
(since no entry calls are permitted inside a protected_body).
14
For an
accept_statement,
the innermost enclosing body shall be a
task_body,
and the
entry_direct_name
shall denote an
entry_declaration
in the corresponding task declaration; the profile of the
accept_statement
shall conform fully to that of the corresponding
entry_declaration.
{full conformance (required)} An
accept_statement shall have a parenthesized
entry_index if and only if the corresponding
entry_declaration has a
discrete_subtype_definition.
15
An accept_statement
shall not be within another accept_statement
that corresponds to the same entry_declaration,
nor within an asynchronous_select
inner to the enclosing task_body.
15.a
Reason: Accept_statements
are required to be immediately within the enclosing task_body
(as opposed to being in a nested subprogram) to ensure that a nested
task does not attempt to accept the entry of its enclosing task. We considered
relaxing this restriction, either by making the check a run-time check,
or by allowing a nested task to accept an entry of its enclosing task.
However, neither change seemed to provide sufficient benefit to justify
the additional implementation burden.
15.b
Nested accept_statements
for the same entry (or entry family) are prohibited to ensure that there
is no ambiguity in the resolution of an expanded name for a formal parameter
of the entry. This could be relaxed by allowing the inner one to hide
the outer one from all visibility, but again the small added benefit
didn't seem to justify making the change for Ada 95.
15.c
Accept_statements
are not permitted within asynchronous_select
statements to simplify the semantics and implementation: an accept_statement
in an abortable_part could result
in Tasking_Error being propagated from an entry call even though the
target task was still callable; implementations that use multiple tasks
implicitly to implement an asynchronous_select
might have trouble supporting "up-level" accepts. Furthermore,
if accept_statements were permitted
in the abortable_part, a task could
call its own entry and then accept it in the abortable_part,
leading to rather unusual and possibly difficult-to-specify semantics.
16
{requires a completion (protected
entry_declaration) [partial]} An
entry_declaration
of a protected unit requires a completion[, which shall be an
entry_body,]
{only as a completion (entry_body) [partial]}
and every
entry_body
shall be the completion of an
entry_declaration
of a protected unit.
{completion legality (entry_body)
[partial]} The profile of the
entry_body
shall conform fully to that of the corresponding declaration.
{full
conformance (required)}
16.a
Ramification: An entry_declaration,
unlike a subprogram_declaration,
cannot be completed with a renaming_declaration.
16.b
To be honest: The completion
can be a pragma Import, if the implementation
supports it.
16.c
Discussion: The above applies
only to protected entries, which are the only ones completed with entry_bodies.
Task entries have corresponding accept_statements
instead of having entry_bodies,
and we do not consider an accept_statement
to be a ``completion,'' because a task entry_declaration
is allowed to have zero, one, or more than one corresponding accept_statements.
17
An
entry_body_formal_part
shall have an
entry_index_specification
if and only if the corresponding
entry_declaration
has a
discrete_subtype_definition. In this
case, the
discrete_subtype_definitions
of the
entry_declaration and the
entry_index_specification
shall fully conform to one another (see
6.3.1).
{full conformance (required)}
18
A name that denotes a formal parameter of an
entry_body is not allowed within
the entry_barrier of the entry_body.
Static Semantics
19
The parameter modes defined for parameters
in the
parameter_profile of an
entry_declaration
are the same as for a
subprogram_declaration
and have the same meaning (see
6.2).
19.a
Discussion: Note that access
parameters are not allowed for task entries (see above).
20
{family (entry)}
{entry family} {entry
index subtype} An
entry_declaration
with a
discrete_subtype_definition (see
3.6) declares a
family of distinct entries
having the same profile, with one such entry for each value of the
entry
index subtype defined by the
discrete_subtype_definition.
[A name for an entry of a family takes the form of an
indexed_component,
where the
prefix denotes the
entry_declaration
for the family, and the index value identifies the entry within the family.]
{single entry} {entry
(single)} The term
single entry is used
to refer to any entry other than an entry of an entry family.
21
In the
entry_body
for an entry family, the
entry_index_specification
declares a named constant whose subtype is the entry index subtype defined
by the corresponding
entry_declaration;
{named entry index} the
value of the
named entry index identifies which entry of the family
was called.
21.a
Ramification: The discrete_subtype_definition
of the entry_index_specification
is not elaborated; the subtype of the named constant declared is defined
by the discrete_subtype_definition
of the corresponding entry_declaration,
which is elaborated, either when the type is declared, or when the object
is created, if its constraint is per-object.
Dynamic Semantics
22/1
{
8652/0002}
{elaboration (entry_declaration) [partial]} The
elaboration of an entry_declaration for
an entry family consists of the elaboration of the discrete_subtype_definition,
as described in 3.8.For the elaboration of
an entry_declaration for an entry family,
if the discrete_subtype_definition contains
no per-object expressions (see 3.8), then the discrete_subtype_definition
is elaborated. Otherwise, the elaboration of the entry_declaration
consists of the evaluation of any expression of the discrete_subtype_definition
that is not a per-object expression (or part of one). The elaboration of
an
entry_declaration for a single entry
has no effect.
22.a
Discussion: The elaboration of the
declaration of a protected subprogram has no effect, as specified in clause
6.1. The default initialization of an object of a
task or protected type is covered in 3.3.1.
23
[The actions to be performed when an entry is
called are specified by the corresponding accept_statements
(if any) for an entry of a task unit, and by the corresponding entry_body
for an entry of a protected unit.]
24
{execution (accept_statement)
[partial]} For the execution of an
accept_statement,
the
entry_index, if any, is first evaluated
and converted to the entry index subtype; this index value identifies which
entry of the family is to be accepted.
{implicit subtype conversion
(entry index) [partial]} {blocked
(on an accept_statement) [partial]} {selection
(of an entry caller)} Further execution of the
accept_statement is then blocked until
a caller of the corresponding entry is selected (see
9.5.3),
whereupon the
handled_sequence_of_statements,
if any, of the
accept_statement is executed,
with the formal parameters associated with the corresponding actual parameters
of the selected entry call. Upon completion of the
handled_sequence_of_statements,
the
accept_statement completes and is left.
When an exception is propagated from the
handled_sequence_of_statements
of an
accept_statement, the same exception
is also raised by the execution of the corresponding
entry_call_statement.
24.a
Ramification: This is in
addition to propagating it to the construct containing the accept_statement.
In other words, for a rendezvous, the raising splits in two, and continues
concurrently in both tasks.
24.b
The caller gets a new occurrence;
this isn't considered propagation.
24.c
Note that we say ``propagated
from the handled_sequence_of_statements
of an accept_statement'', not ``propagated
from an accept_statement.'' The
latter would be wrong -- we don't want exceptions propagated by the entry_index
to be sent to the caller (there is none yet!).
25
{rendezvous} The
above interaction between a calling task and an accepting task is called
a
rendezvous. [After a rendezvous, the two tasks continue their
execution independently.]
26
[An
entry_body
is executed when the
condition of the
entry_barrier
evaluates to True and a caller of the corresponding single entry, or entry of
the corresponding entry family, has been selected (see
9.5.3).]
{execution (entry_body) [partial]} For
the execution of the
entry_body, the
declarative_part
of the
entry_body is elaborated, and the
handled_sequence_of_statements of the body
is executed, as for the execution of a
subprogram_body.
The value of the named entry index, if any, is determined by the value of the
entry index specified in the
entry_name
of the selected entry call (or intermediate
requeue_statement
-- see
9.5.4).
26.a
To be honest: If the entry
had been renamed as a subprogram, and the call was a procedure_call_statement
using the name declared by the renaming, the entry index (if any) comes
from the entry name specified in
the subprogram_renaming_declaration.
27
22 A task entry has corresponding
accept_statements (zero or more), whereas a protected entry has a corresponding
entry_body (exactly one).
28
23 A consequence of the rule
regarding the allowed placements of accept_statements
is that a task can execute accept_statements
only for its own entries.
29
24 A return_statement
(see 6.5) or a requeue_statement
(see 9.5.4) may be used to complete the execution
of an accept_statement or an entry_body.
29.a
Ramification: An accept_statement
need not have a handled_sequence_of_statements
even if the corresponding entry has parameters. Equally, it can have
a handled_sequence_of_statements
even if the corresponding entry has no parameters.
29.b
Ramification: A single entry overloads
a subprogram, an enumeration literal, or another single entry if they have the
same defining_identifier. Overloading is
not allowed for entry family names. A single entry or an entry of an entry family
can be renamed as a procedure as explained in 8.5.4.
30
25 The condition
in the entry_barrier may reference
anything visible except the formal parameters of the entry. This includes
the entry index (if any), the components (including discriminants) of
the protected object, the Count attribute of an entry of that protected
object, and data global to the protected unit.
31
The restriction against referencing
the formal parameters within an entry_barrier
ensures that all calls of the same entry see the same barrier value.
If it is necessary to look at the parameters of an entry call before
deciding whether to handle it, the entry_barrier
can be ``when True'' and the caller can be requeued (on some private
entry) when its parameters indicate that it cannot be handled immediately.
Examples
32
Examples of
entry declarations:
33
entry Read(V : out Item);
entry Seize;
entry Request(Level)(D : Item); -- a family of entries
34
Examples of accept
statements:
35
accept Shut_Down;
36
accept Read(V : out Item) do
V := Local_Item;
end Read;
37
accept Request(Low)(D : Item) do
...
end Request;
Extensions to Ada 83
37.a
{extensions to Ada 83}
The syntax rule for entry_body
is new.
37.b
Accept_statements
can now have exception_handlers.
Contents Index Previous Next Legal