9.5 Intertask Communication
{intertask communication}
{critical section:
See intertask communication} The primary
means for intertask communication is provided by calls on entries and
protected subprograms. Calls on protected subprograms allow coordinated
access to shared data objects. Entry calls allow for blocking the caller
until a given condition is satisfied (namely, that the corresponding
entry is open — see
9.5.3), and then
communicating data or control information directly with another task
or indirectly via a shared protected object.
Static Semantics
{target
object (of a call on an entry or a protected subprogram)}
Any call on an entry or on a protected subprogram
identifies a
target object for the operation, which is either
a task (for an entry call) or a protected object (for an entry call or
a protected subprogram call). The target object is considered an implicit
parameter to the operation, and is determined by the operation
name
(or
prefix)
used in the call on the operation, as follows:
If it is a
direct_name
or expanded name that denotes the declaration (or body) of the operation,
then the target object is implicitly specified to be the current instance
of the task or protected unit immediately enclosing the operation;
{internal
call} such a call is defined to be an
internal call;
If it is a
selected_component
that is not an expanded name, then the target object is explicitly specified
to be the task or protected object denoted by the
prefix
of the
name;
{external call} such
a call is defined to be an
external call;
Discussion: For example:
protected type Pt is
procedure Op1;
procedure Op2;
end Pt;
PO : Pt;
Other_Object : Some_Other_Protected_Type;
protected body Pt is
procedure Op1 is begin ... end Op1;
procedure Op2
is
begin
Op1; --
An internal call.
Pt.Op1; --
Another internal call.
PO.Op1; --
An external call. It the current instance is PO, then
--
this is a bounded error (see 9.5.1).
Other_Object.Some_Op; --
An external call.
end Op2;
end Pt;
If the
name
or
prefix
is a dereference (implicit or explicit) of an access-to-protected-subprogram
value, then the target object is determined by the
prefix
of the Access
attribute_reference
that produced the access value originally, and the call is defined to
be an
external call;
{target object (of
a requeue_statement)} {internal
requeue} {external
requeue} A corresponding definition of
target object applies to a
requeue_statement
(see
9.5.4), with a corresponding distinction
between an
internal requeue and an
external requeue.
Legality Rules
{
AI95-00345-01}
The view of the target protected object associated with a call of a protected
procedure or entry shall be a variable.
Dynamic Semantics
Within the body of a protected operation, the current
instance (see
8.6) of the immediately enclosing
protected unit is determined by the target object specified (implicitly
or explicitly) in the call (or requeue) on the protected operation.
To be honest: The current instance is
defined in the same way within the body of a subprogram declared immediately
within a
protected_body.
Any call on a protected procedure or entry of a target
protected object is defined to be an update to the object, as is a requeue
on such an entry.
Reason: Read/write access to the components
of a protected object is granted while inside the body of a protected
procedure or entry. Also, any protected entry call can change the value
of the Count attribute, which represents an update. Any protected procedure
call can result in servicing the entries, which again might change the
value of a Count attribute.
Wording Changes from Ada 95
{
AI95-00345-01}
Added a Legality Rule to make it crystal-clear that the protected object
of an entry or procedure call must be a variable. This rule was implied
by the Dynamic Semantics here, along with the Static Semantics of
3.3,
but it is much better to explicitly say it. While many implementations
have gotten this wrong, this is not an incompatibility — allowing
updates of protected constants has always been wrong.