9.5 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
{
AI05-0225-1}
{
AI05-0291-1}
When a
name
or
prefix
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
or
prefix
determines a
target object, as follows:
To be honest: {
AI05-0291-1}
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).
{
AI05-0291-1}
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;
a
call using such a name is defined to be an
internal call;
{
AI05-0291-1}
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
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;
{
AI05-0291-1}
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; a call using such a name is
defined to be an
external call;
{
AI05-0291-1}
A call on an entry or a protected subprogram either uses a
name
or
prefix
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.
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
Reason: {
AI05-0225-1}
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.
Ramification: {
AI05-0291-1}
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 or
out.
Reason: {
AI125-0166-1}
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: {
AI125-0166-1}
6.1.1 actually defines
"specific precondition expression" and "class-wide precondition
expression". This rule is intended to apply to both.
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.
Syntax
Static Semantics
{
AI05-0215-1}
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
(see
13.1.1):
Synchronization
If specified, the aspect definition shall be a
synchronization_kind.
Aspect Description
for Synchronization: Defines
whether a given primitive operation of a synchronized interface will must
be implemented by an entry or protected procedure.
{
AI05-0030-2}
{
AI05-0215-1}
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.
Legality Rules
{
AI05-0030-2}
{
AI05-0215-1}
A procedure for which the specified
synchronization_kind
is By_Entry shall be implemented by an entry. A procedure for which the
specified
synchronization_kind
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).
{
AI05-0030-2}
{
AI05-0215-1}
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.
{
AI05-0030-2}
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.
Static Semantics
{
AI12-0064-2}
{
AI12-0374-2}
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:
Nonblocking
This aspect specifies the blocking restriction
for the entity; it shall be specified by a static Boolean expression.
[The aspect_definition
can be omitted from the specification of this aspect; in that case, the
aspect for the entity is True.]
Aspect Description
for Nonblocking: Specifies
that an associated subprogram does not block.
Proof: 13.1.1
allows omitting the aspect expression
for any aspect with type Boolean; we take advantage of that here.
{
AI12-0064-2}
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
formal parameters.
Ramification: The
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.
{
AI12-0064-2}
{
AI12-0374-2}
{
AI12-0439-1}
When aspect Nonblocking is False for an entity,
the entity can 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.
Ramification: Specifying
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.
{
AI12-0064-2}
{
AI12-0374-2}
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 aspect
of the generic unit combined with the Nonblocking aspects of the formals
where they are used, and if that is overridden on the instance, the instance
body might make calls that allow blocking in subprograms that are declared
nonblocking.
{
AI12-0064-2}
{
AI12-0374-2}
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.
{
AI12-0064-2}
{
AI12-0374-2}
For an enumeration literal, the Nonblocking aspect
is True.
Reason: Enumeration
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
are meaningful.
{
AI12-0064-2}
{
AI12-0374-2}
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.
Reason: Predefined
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.
Ramification: It's
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.
{
AI12-0064-2}
For a dereference of an access-to-subprogram type,
the Nonblocking aspect of the designated subprogram is that of the access-to-subprogram
type.
{
AI12-0374-2}
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.
{
AI12-0064-2}
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.
{
AI12-0064-2}
Unless directly specified, overridings of dispatching
operations inherit this aspect.
{
AI12-0064-2}
{
AI12-0374-2}
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
type.
{
AI12-0064-2}
{
AI12-0374-2}
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.
Discussion: The
expressions that can be specified for a such a subtype are limited by
a Legality Rule, see below.
{
AI12-0064-2}
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.
{
AI12-0064-2}
{
AI12-0374-2}
If not specified for a library unit, the Nonblocking
aspect 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.
{
AI12-0064-2}
If a language-defined subprogram allows blocking,
then a call on the subprogram is a potentially blocking operation.
Ramification: Calls
on other subprograms that allow blocking are not themselves potentially
blocking; the execution of the body could execute a potentially blocking
operation.
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.
Legality Rules
{
AI12-0064-2}
{
AI12-0267-1}
{
AI12-0374-2}
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.
{
AI12-0374-2}
Furthermore, 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).
{
AI12-0374-2}
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.
Reason: 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 construct check.
Ramification: Implicit
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).
Discussion: We
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.
{
AI12-0064-2}
{
AI12-0374-2}
For the purposes of the above rules, an entry_body
is considered nonblocking if the immediately enclosing protected unit
is nonblocking.
Reason: An entry
declaration always allows blocking (by rule); but we want to be able
to compile-time check for most violations of the 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. We can't do this
checking unconditionally, as that would be incompatible: existing Ada
protected units might call subprograms that allow blocking. Thus a protected
unit that allows blocking (which is the default) must allow calling any
subprogram from an entry body.
{
AI12-0374-2}
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
unit.
{
AI12-0064-2}
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.
Discussion: Rules
elsewhere in the standard (4.6 and 3.10.2)
ensure that access-to-subprogram conversion and the Access attribute
enforce nonblocking.
Ramification: A
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.)
{
AI12-0064-2}
{
AI12-0374-2}
{
AI12-0396-1}
{
AI12-0399-1}
It is illegal to directly specify aspect Nonblocking
for the first subtype of the full view of a type that has a partial view.
If the Nonblocking aspect of the full view is inherited, it shall have
the same value as that of the partial view, or have the value True.
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.
{
AI12-0064-2}
{
AI12-0374-2}
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.
Reason: Boolean-valued
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.
{
AI12-0319-1}
For an access-to-object type that is nonblocking,
the Allocate, Deallocate, and Storage_Size operations on its storage
pool shall be nonblocking.
Ramification: Standard
storage pools always have nonblocking operations by definition (see 13.11),
so this rule only can fail for user-defined storage pools.
{
AI12-0319-1}
For a composite type that is nonblocking:
All component subtypes shall
be nonblocking;
For a record type or extension,
every call in the default_expression
of a component (including discriminants) shall call an operation that
is nonblocking;
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 ensures that if
a generic formal type is nonblocking, all of the basic operations of
the actual type are nonblocking.
Default initialization,
finalization, and assignment of elementary types are always nonblocking,
so we don't need any rules for those.
{
AI12-0064-2}
{
AI12-0374-2}
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
and:
for a record type or record
extension, the parent primitive "=" allows blocking; or
some component is of a type
T, and:
T is a record
type or record extension that has a primitive "=" that allows
blocking; or
T is neither
a record type nor a record extension, and T has a predefined "="
that allows blocking.
Ramification: This
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;
Ramification: We
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
of 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.
{
AI12-0064-2}
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
unit.
Ramification: For
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
{
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.
Extensions to Ada 2005
{
AI05-0030-2}
{
AI05-0215-1}
Added the Synchronization aspect to allow specifying
that an interface procedure is really an entry or a protected procedure.
Wording Changes from Ada 2005
{
AI05-0225-1}
Correction: 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
{
AI12-0064-2}
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
{
AI12-0166-1}
Correction: Internal
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
{
AI12-0064-2}
{
AI12-0319-1}
{
AI12-0374-2}
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