9.5.2 Entries and Accept Statements
Syntax
Proof: This follows from the BNF.
Reason: An entry family can never implement
something, so allowing an indicator is felt by the majority of the ARG
to be redundant.
Name Resolution Rules
Proof: The only declarations that occur
immediately within the declarative region of an
accept_statement
are those for its formal parameters.
Legality Rules
An
entry_declaration
in a task declaration shall not contain a specification for an access
parameter (see
3.10).
Reason: Access
parameters for task entries would require a complex implementation. For
example:
task T is
entry E(Z : access Integer); -- Illegal!
end T;
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;
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.
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).
if the
overriding_indicator
is
not overriding, then the entry shall not implement any inherited
subprogram.
{generic contract
issue [partial]} In addition to the places
where Legality Rules normally apply (see
12.3),
these rules also apply in the private part of an instance of a generic
unit.
Discussion: These rules are subtly different
than those for subprograms (see
8.3.1) because
there cannot be “late” inheritance of primitives from interfaces.
Hidden (that is, private) interfaces are prohibited explicitly (see
7.3),
as are hidden primitive operations (as private operations of public abstract
types are prohibited — see
3.9.3).
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.
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.
{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)}
To be honest: The completion can be a
pragma Import,
if the implementation supports it.
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.
Static Semantics
Discussion: Note that access parameters
are not allowed for task entries (see above).
{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.
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.
Dynamic Semantics
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.
[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.]
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.
The caller gets a new occurrence; this isn't
considered propagation.
{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.]
23 A task entry has corresponding accept_statements
(zero or more), whereas a protected entry has a corresponding entry_body
(exactly one).
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.
26 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.
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
Examples of entry
declarations:
entry Read(V : out Item);
entry Seize;
entry Request(Level)(D : Item); -- a family of entries
Examples of accept
statements:
accept Shut_Down;
accept Read(V : out Item) do
V := Local_Item;
end Read;
accept Request(Low)(D : Item) do
...
end Request;
Extensions to Ada 83
{
extensions to Ada 83}
The
syntax rule for
entry_body
is new.
Wording Changes from Ada 95