9.5 Intertask Communication
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.
When a name
denotes an entry, protected subprogram, or a prefixed view of a primitive
subprogram of a limited interface whose first parameter is a controlling
parameter, the name
determines a target object
, as follows:
To be honest:
This wording uses "denotes" to mean "denotes a view of
an entity" (when the term is used in Legality Rules), and "denotes
an entity" (when the term is used in Dynamic Semantics rules). It
does not mean "view of a declaration", as that would not include
renames (a renames is not an entry or protected subprogram).
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;
call using such a name 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 object denoted by the prefix
of the name
a call using such a name is defined to be an external
Discussion: For example:
protected type Pt is
PO : Pt;
Other_Object : Some_Other_Protected_Type;
protected body Pt is
procedure Op1 is begin ... end Op1;
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.
If the name
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; a call using such a name is
defined to be an external call
A call on an entry or a protected subprogram either uses a name
that determines a target object implicitly, as above, or is a call on
(a non-prefixed view of) a primitive subprogram of a limited interface
whose first parameter is a controlling parameter, in which case the target
object is identified explicitly by the first parameter. This latter case
is an external call
corresponding definition of target object applies to a requeue_statement
), with a corresponding distinction
between an internal requeue
and an external requeue
The point is to prevent any calls to such a name
whose target object is a constant view of a protected object, directly,
or via an access value, renames, or generic formal subprogram. It is,
however, legal to say P'Count in a protected function body, even though
the protected object is a constant view there.
This rule does not apply to calls that are not to a prefixed view. Specifically
a "normal" call to a primitive operation of a limited interface
is not covered by this rule. In that case, the normal parameter passing
mode checks will prevent passing a constant protected object to an operation
implemented by a protected entry or procedure as the mode is required
to be in out
These calls will be made before the start of the
protected action, and thus would not be subject to the expected mutual
exclusion. As such, they would be an automatic race condition (the state
of the called object could change before the start of the protected action
for the call on the protected entry or subprogram).
To be honest:
6.1.1 actually defines
"specific precondition expression" and "class-wide precondition
expression". This rule is intended to apply to both.
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.
For the declaration of a primitive procedure of a synchronized tagged
type the following language-defined representation aspect may be specified
with an aspect_specification
If specified, the aspect definition shall be a synchronization_kind
Aspect Description for Synchronization:
Defines whether a given primitive operation of a synchronized interface
must be implemented by an entry or protected procedure.
Inherited subprograms inherit the Synchronization aspect, if any, from
the corresponding subprogram of the parent or progenitor type. If an
overriding operation does not have a directly specified Synchronization
aspect then the Synchronization aspect of the inherited operation is
inherited by the overriding operation.
A procedure for which the specified synchronization_kind
is By_Entry shall be implemented by an entry. A procedure for which the
is By_Protected_Procedure shall be implemented by a protected procedure.
A procedure for which the specified synchronization_kind
is Optional may be implemented by an entry or by a procedure (including
a protected procedure).
If a primitive procedure overrides an inherited operation for which the
Synchronization aspect has been specified to be By_Entry or By_Protected_Procedure,
then any specification of the aspect Synchronization applied to the overriding
operation shall have the same synchronization_kind
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.
For a program unit, task entry, formal package,
formal subprogram, formal object of an anonymous access-to-subprogram
type, enumeration literal, and for a subtype (including a formal subtype),
the following language-defined operational aspect is defined:
This aspect specifies the blocking restriction
for the entity; it shall be specified by a static Boolean expression.
can be omitted from the specification of this aspect; in that case the
nonblocking expression for the entity is the enumeration literal True.]
for Nonblocking: Specifies
that an associated subprogram does not block.
allows omitting the aspect expression
for any aspect with type Boolean; we take advantage of that here.
The Nonblocking aspect may be specified for all
entities for which it is defined, except for protected operations and
task entries. In particular, Nonblocking may be specified for generic
Nonblocking aspect cannot be specified for predefined operators or enumeration
literals but we don't need to mention that above. One would have to declare
a subprogram in order to specify the aspect in those cases, but that
defines a user-defined subprogram which is itself not a predefined operator
or an enumeration literal.
When aspect Nonblocking is False for an entity,
the entity might contain a potentially blocking operation; such an entity
allows blocking. If the aspect is True for an entity, the entity
is said to be nonblocking.
Nonblocking as False imposes no restrictions. Specifying Nonblocking
as True imposes additional compile-time checks to prevent blocking, but
does not prevent deadlock. A pragma Detect_Blocking can be used to ensure
that Program_Error is raised in a deadlock situation.
For a generic instantiation and entities declared
within such an instance, the aspect is determined by the Nonblocking
aspect for the corresponding entity of the generic unit, anded
with the Nonblocking aspects of the actual generic parameters used
by the entity. If the aspect is directly specified for an instance, the
specified expression shall have the same value as the Nonblocking aspect
of the instance (after anding with the aspects of the used actual
parameters). In the absence of a Use_Formal aspect, all actual generic
parameters are presumed to be used by an entity (see H.7.1).
Reason: We want
to allow confirming aspects for instances, but nothing else. The Legality
Rules of the generic body were checked assuming the nonblocking expression
of the generic unit, and if that is changed, the instance body might
make calls that allow blocking in subprograms that are declared nonblocking.
For a (protected or task) entry, the Nonblocking
aspect is False.
Reason: An entry
can be renamed as a procedure, so the value of the aspect has to be well-defined
(as the attribute can be applied to a procedure). We do not want a nonblocking
subprogram to be able to call an entry, no matter how it occurs, so the
value ought to be False. Moreover, we do not want a subprogram that renames
an entry to be able to override a nonblocking subprogram. We could have
used individual rules for these cases, but there were already many of
them, and this solution avoids the need for extra rules for entries.
For an enumeration literal, the Nonblocking aspect
literals can be renamed as functions, and passed to generic formal functions,
so we need to define the value of the aspect to ensure the other rules
For a predefined operator of an elementary type,
the Nonblocking aspect is True. For a predefined operator of a composite
type, the Nonblocking aspect of the operator is the same as the Nonblocking
aspect for the type.
operators of elementary types can never include any potentially blocking
operations, so we want them to declare that. Record equality can be composed
of operations including user-defined "=" operators, which might
allow blocking. Array equality might use some record equality. So we
have to have the possibility of allowing blocking for them. We don't
just copy the Nonblocking aspect of the type in every case, as someone
could declare an elementary type to allow blocking.
not possible to specify the nonblocking expression of a predefined operator;
if an operator is declared in order to do that, it is no longer predefined.
For a dereference of an access-to-subprogram type,
the Nonblocking aspect of the designated subprogram is that of the access-to-subprogram
For the base subtype of a scalar (sub)type, the
Nonblocking aspect is True.
Reason: The first
subtype of a scalar type can allow blocking (which can be useful so a
predicate can allow blocking), but the base subtype is always Nonblocking.
We need this so the Nonblocking value is well-defined for any subtype
that is built from the base subtype (T'Base). T'Base of any scalar type,
including a generic formal type, is always nonblocking.
For an inherited primitive dispatching subprogram
that is null or abstract, the subprogram is nonblocking if and only if
a corresponding subprogram of at least one ancestor is nonblocking. For
any other inherited subprogram, it is nonblocking if and only if the
corresponding subprogram of the parent is nonblocking.
Unless directly specified, overridings of dispatching
operations inherit this aspect.
Unless directly specified, for a formal subtype,
formal package, or formal subprogram, the Nonblocking aspect is that
of the actual subtype, package, or subprogram.
Reason: This means
that Nonblocking legality checking for the actual parameters of the instance
is only necessary when the aspect is explicitly specified for the formal
Unless directly specified, for a non-first subtype
S, the Nonblocking aspect is that of the subtype identified in
the subtype_indication defining S; unless directly specified for
the first subtype of a derived type, the Nonblocking aspect is that of
the ancestor subtype.
expressions that can be specified for a such a subtype are limited by
a Legality Rule, see below.
Unless directly specified, for any other program
unit, first subtype, or formal object, the Nonblocking aspect of the
entity is determined by the Nonblocking aspect for the innermost program
unit enclosing the entity.
If not specified for a library unit, the nonblocking
expression is True if the library unit is declared pure, or False otherwise.
Reason: The primary
purpose of these rules is to define what operations are not allowed in
a protected operation (blocking is not allowed). Some of these operations
are not directly blocking. However, they are still treated as potentially
blocking, because allowing them in a protected action might impose an
undesirable implementation burden.
task creation or activation;
during a protected action,
an external call on a protected subprogram (or an external requeue) with
the same target object as that of the protected action.
Reason: This is
really a deadlocking call, rather than a blocking call, but we include
it in this list for simplicity.
If a language-defined subprogram allows blocking,
then a call on the subprogram is a potentially blocking operation.
on other subprograms that allow blocking are not themselves potentially
blocking; the execution of the body could execute a potentially blocking
A user-defined instance
of a language-defined generic creates user-defined subprograms for the
purpose of this rule. A dispatching call to a language-defined abstract
subprogram always calls a user-defined concrete subprogram, so that too
is not potentially blocking for the purposes of this rule.
A portion of program text is called a nonblocking
region if it is anywhere within a parallel construct,
or if the innermost enclosing program unit is nonblocking. A nonblocking
region shall not contain any of the following:
task creation or activation.
Futhermore, a parallel construct shall neither
contain a call on a callable entity for which the Nonblocking aspect
is False, nor shall it contain a call on a callable entity declared within
a generic unit that uses a generic formal parameter with Nonblocking
aspect False (see Use_Formal aspect in H.7.1).
Finally, a nonblocking region that is outside of
a parallel construct shall not contain a call on a callable entity for
which the Nonblocking aspect is False, unless the region is within a
generic unit and the callable entity is associated with a generic formal
parameter of the generic unit, or the call is within the aspect_definition
of an assertion aspect for an entity that allows blocking.
A generic unit or entity declared within one is
presumed to use its "used" generic formal parameters at least
once each time it is invoked, and this passes through to the parallel
calls for finalization, storage pools, and the like are covered by the
above prohibition. The rules above say “a call”, not “an
explicit call”. Such calls are considered statically bound when
that is possible, that is, when the controlling object has a known specific
type (even if the actual implementation uses dispatching).
don't need to worry specially about entry calls (even if the entry has
been renamed as a procedure), as they will be detected by the prohibition
against calls to entities with the Nonblocking aspect False.
Similarly, we don't need
to specially worry about subprograms of limited interfaces that are implemented
by entries, as any such subprogram necessarily has the value statically
False for the Nonblocking aspect, and thus is already covered by the
prohibition against calling such subprograms.
For the purposes of the above rules, an entry_body
is considered nonblocking if the immediately enclosing protected unit
Reason: An entry
always allows blocking (by rule); but we want to be able to compile-time
check for most violations of prohibition against potentially blocking
operations in a protected action (see 9.5.1).
We do that by using the nonblocking status of the protected unit as the
controlling factor, and enforce that by not allowing the specification
of the Nonblocking aspect for any protected operation.
For a subtype for which aspect Nonblocking is True,
any predicate expression that applies to the subtype shall only contain
constructs that are allowed immediately within a nonblocking program
A subprogram shall be nonblocking if it overrides
a nonblocking dispatching operation. An entry shall not implement a nonblocking
procedure. If an inherited dispatching subprogram allows blocking, then
the corresponding subprogram of each ancestor shall allow blocking.
elsewhere in the standard (4.6 and 3.10.2)
ensure that access-to-subprogram conversion and the Access attribute
nonblocking subprogram can override one that allows blocking, but the
reverse is illegal. Thus one can declare a Finalize subprogram to be
nonblocking, even though it overrides a routine that allows blocking.
(This works because a nonblocking subprogram allows a strict subset of
the operations allowed in allows blocking subprograms, so calling such
a subprogram as if it allows blocking — as is necessary in a dispatching
call — is harmless.)
AIt is illegal to specify aspect Nonblocking for
the first subtype of the full view of a type that has a partial or incomplete
Reason: We need
completions to agree on nonblocking with the original view. One reason
this is necessary to prevent the predefined equality operator from being
nonblocking in the partial view and allowing blocking in the full view.
Aspect Nonblocking shall be directly specified
for the first subtype of a derived type only if it has the same value
as the Nonblocking aspect of the ancestor subtype or if it is specified
True. Aspect Nonblocking shall be directly specified for a nonfirst subtype
S only if it has the same value as the Nonblocking aspect of the
subtype identified in the subtype_indication
defining S or if it is specified True.
aspects have a similar rule to the first rule here (see 13.1.1),
we want this one to work similarly. We need non-first subtypes to allow
blocking only if the original first subtype allows blocking, as that
allows the programmer to know that any operation on any subtype of a
type are nonblocking if the first subtype is nonblocking.
For a composite type that is nonblocking:
All component subtypes shall
For a record type or extension,
every call in the default_expression
of a component (including discriminants) shall call an operation that
For a controlled type, the
Initialize, Finalize, and Adjust (if any) subprograms shall be nonblocking.
Reason: These rules
ensure that if a type is nonblocking, the default initialization, finalization,
and assignment of the type are also nonblocking. This allows the use
of the nonblocking attribute of a generic formal type to describe whether
these operations of the type allow blocking.
finalization, and assignment of elementary types are always nonblocking,
so we don't need any rules for those.
The predefined equality operator for a composite
type, unless it is for a record type or record extension and the operator
is overridden by a primitive equality operator, is illegal if it is nonblocking
for a record type or record
extension, the parent primitive "=" allows blocking; or
some component is of a record
type or record extension that has a primitive "=" that allows
some component is of a type,
other than a record type or a record extension, that has a predefined
"=" that allows blocking.
applies to both record and array "=".
This check occurs when
the equality operator is declared, so this rule effectively makes the
type illegal if the rule is violated.
Reason: We don't
need to check this when the operator is overridden for a record type,
as the body of the new definition of equality will enforce the rules,
and there is no case where the predefined operator will re-emerge. We
do have to check this for array types even if the operator is overridden,
as the predefined operator will re-emerge in generics and record equality.
the actual subprogram corresponding
to a nonblocking formal subprogram shall be nonblocking [(an actual that
is an entry is not permitted in this case)];
the actual subtype corresponding
to a nonblocking formal subtype shall be nonblocking;
require matching for formal scalar or access-to-object types, even though
their predefined operators are always nonblocking (and they re-emerge
in the generic unit) - because a "blocking" predicate might
apply to the actual subtype, which will also be enforced on operations
on the formal type.
the actual object corresponding
to a formal object of a nonblocking access-to-subprogram type shall be
of a nonblocking access-to-subprogram type;
the actual instance corresponding
to a nonblocking formal package shall be nonblocking.
In addition to the places where
Legality Rules normally apply (see 12.3),
the above rules also apply in the private part of an instance of a generic
a generic formal parameter to be nonblocking (thus, for these rules to
apply), it has to explicitly specify aspect Nonblocking to be True. However,
if not specified True, these rules do apply in the instance of the specification
of the generic unit (the normal re-checking is needed). For instance,
the body of an expression function might make a prohibited call.
Wording Changes from Ada 95
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.
Extensions to Ada 2005
Added the Synchronization aspect to allow specifying
that an interface procedure is really an entry or a protected procedure.
Wording Changes from Ada 2005
Clarified that the target object of any name denoted
a protected procedure or entry can never be a constant (other than for
the 'Count attribute). This closes holes involving calls to access-to-protected,
renaming as a procedure, and generic formal subprograms.
Inconsistencies With Ada 2012
Calls on procedures that rename
an entry or are implemented by an entry are now defined to be potentially
blocking. This means that such a call now might raise Program_Error.
However, it never made sense for some entry calls to be excluded from
being potentially blocking, and we expect that most implementations already
treated all entry calls the same way. Thus do not expect this wording
change to actually change the behavior of any implementation, and thus
no program will change.
Incompatibilities With Ada 2012
protected calls are now prohibited in preconditions and default expressions
of protected operations. These were allowed in Ada 2012, but as they
cause race conditions and as most existing Ada 95 compilers crash when
given such a default parameter, we expect such code to be extremely rare.
Extensions to Ada 2012
Aspect Nonblocking is new;
it allows compile-time checks to prevent using potentially blocking operations
in contexts where that is not allowed.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe