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
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
a static expression;
a call to a predefined boolean logical operator
and where each operand is nonblocking-static;
an and then short-circuit control form where
each operand is nonblocking-static;
Reason: We define the term “nonblocking-static
expression” so that nonblocking
attribute_references
can be used to define the value of other nonblocking aspects, but we
don't allow anything else with a value not known at compile-time.
{
AI12-0064-2}
{
AI12-0374-1}
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 an
expression,
called a
nonblocking expression.
If directly
specified, the
aspect_definition
shall be a nonblocking-static expression. The expected type for the
expression
is the predefined type Boolean. [The
aspect_definition
can be omitted from the specification of this aspect; in that case the
nonblocking expression for the entity is the enumeration literal 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}
When the nonblocking expression is static for an entity, the expression
is evaluated to produce a static value for the aspect. When aspect Nonblocking
is statically False for an entity, the entity might contain a potentially
blocking operation; such an entity
allows blocking. If the aspect
is statically True for an entity, the entity is said to be
nonblocking.
Discussion: We have to allow the aspect
to be described as an expression inside of generic units, where the actual
value of the aspect in an instance could be determined by the aspect
of one or more actuals. Our intent is that the expression is always a
static expression outside of any generic unit, and that in such contexts
it is treated more like a static value than an expression.
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-0374-1}
For a generic unit
G, if the aspect Nonblocking is statically
true for
G (by inheritance or specification), then the nonblocking
expression for
G is the
and of the nonblocking attribute
for each formal parameter of
G.
Reason: This means that an instance of
this generic will be nonblocking only if all of the formal parameters
are nonblocking (see below). This is the most usable definition. If one
wants a generic whose instantiations will always be nonblocking, Nonblocking
can be specified on the formal parameters.
{
AI12-0064-2}
For a generic instantiation and entities declared within such an instance,
the aspect is determined by the nonblocking expression for the corresponding
entity of the generic unit, with any Nonblocking attributes of the generic
formal parameters replaced by the appropriate nonblocking expression
of the corresponding actual parameters. If the aspect is directly specified
for an instance, the specified expression shall be static and have the
same value as the nonblocking expression of the instance (after replacement).
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 nonblocking.
Ramification: If the nonblocking expression
of the instance is not static (if the instance is itself inside of a
generic unit), then the Nonblocking aspect cannot be specified for the
instance.
{
AI12-0064-2}
For a (protected or task) entry, the Nonblocking aspect is the Boolean
literal 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}
For an enumeration literal, the Nonblocking aspect is the Boolean literal
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}
For a predefined operator of an elementary type, the Nonblocking aspect
is the Boolean literal 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-1}
For the base type of a scalar (sub)type, the Nonblocking aspect is the
Boolean literal 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 type is always Nonblocking. We need this so the
Nonblocking value is well-defined for any subtype that is built from
the base type (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-1}
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}
Unless directly specified, for a derived type, the Nonblocking aspect
is that of the parent type.
Discussion: The expressions that can
be specified for a derived type are limited by a Legality Rule, see below.
{
AI12-0064-2}
Unless directly specified, for any other program unit, type, 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}
If not specified for a library unit, the nonblocking expression is the
Boolean literal True if the library unit is declared pure and is not
a generic unit, or the Boolean literal False otherwise.
{
AI12-0064-2}
For a
prefix
S that denotes a subprogram (including a formal subprogram), the following
attribute is defined:
S'Nonblocking
{
AI12-0064-2}
Denotes whether subprogram S is considered nonblocking; the type of this
attribute is the predefined type Boolean.
The
prefix
S shall statically denote a subprogram.
Ramification: The evaluation of the
prefix
S will have no effect, which is necessary for S'Nonblocking to be static.
For the intended use in aspect specifications, we don't want any evaluation,
as it would happen at some freezing point.
S'Nonblocking represents the nonblocking
expression of S; evaluation of S'Nonblocking evaluates that expression.
{
AI12-0064-2}
For a
prefix
P that denotes a package (including a formal package), the following
attribute is defined:
P'Nonblocking
{
AI12-0064-2}
Denotes whether package P is considered nonblocking; the type of this
attribute is the predefined type Boolean. P'Nonblocking represents the
nonblocking expression of P; evaluation of P'Nonblocking evaluates that
expression.
{
AI12-0064-2}
For a
prefix
S that denotes a subtype (including formal subtypes), the following attribute
is defined:
S'Nonblocking
{
AI12-0064-2}
{
AI12-0319-1}
{
AI12-0374-1}
Denotes whether default initialization, finalization, assignment, predefined
operators, and (in the case of access-to-subprogram subtypes) a subprogram
designated by a value of subtype S are considered nonblocking; the type
of this attribute is the predefined type Boolean. S'Nonblocking represents
the nonblocking expression of S; evaluation of S'Nonblocking evaluates
that expression.
{
AI12-0319-1}
For a
prefix
X that denotes an object, the following attribute is defined:
X'Nonblocking
{
AI12-0319-1}
{
AI12-0374-1}
Denotes whether the subtype of X is considered nonblocking; the type
of this attribute is the predefined type Boolean. X'Nonblocking represents
the nonblocking expression of X; evaluation of X'Nonblocking evaluates
that expression. X'Nonblocking represents the nonblocking expression
of X; evaluation of X'Nonblocking evaluates that expression.
To be honest: In the case when the
prefix
represents the Storage_Pool of some type, this is the specific type of
the associated pool object, if known.
Reason: This attribute, combined with
rules found in
13.11, allow Acc'Storage_Pool'Nonblocking
to describe whether the storage pool of an access type allows blocking.
{
AI12-0374-1}
For a
prefix
X that denotes an object of a class-wide type T'Class, the following
attribute is defined:
X'Nonblocking(dispatching_operation_set)
{
AI12-0374-1}
X'Nonblocking(
dispatching_operation_set)
represents the
and of the Nonblocking aspect of the tagged type
T1 identified by the tag of X, and the Nonblocking aspects of
the dispatching operations of
T1 corresponding to the specified
dispatching operations of T (or all dispatching operations of T if the
set is the reserved word
all). If a
dispatching_selector_name
within the set denotes multiple dispatching operations of T, the Nonblocking
aspects of all of the corresponding dispatching operations of
T1
are
anded together.
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}
A parallel construct or a nonblocking program unit shall not contain,
other than within nested units with Nonblocking specified as statically
False, a call on a callable entity for which the Nonblocking aspect is
statically False, nor shall it contain any of the following:
task creation or activation.
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}
For the purposes of the above rule, an
entry_body
is considered nonblocking if the immediately enclosing protected unit
is nonblocking.
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.
{
AI12-0374-1}
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}
It is illegal to specify aspect Nonblocking for the full view of a type
that has a partial view.
Ramification: The aspect should be specified
on the partial view for such a type. 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-1}
Aspect Nonblocking shall be specified for the first subtype of a derived
type only if it fully conforms to the nonblocking expression of the ancestor
subtype or if it is specified to have the Boolean literal True. Aspect
Nonblocking shall be specified for a nonfirst subtype
S only if
it fully conforms to the nonblocking expression of the subtype identified
in the
subtype_indication
defining
S or if it is specified to have the Boolean literal True.
Aspect Nonblocking shall be specified for a first subtype
S that
completes an incomplete or partial view
P only if it fully conforms
to the nonblocking expression of the subtype
P or if it is specified
to have the Boolean literal 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. For the other rules, we need non-first
subtypes and completions 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-0064-2}
If aspect Nonblocking is specified for an entity that is not a generic
unit or declared inside of a generic unit, the
aspect_definition
shall be a static expression.
{
AI12-0064-2}
If the prefix of a Nonblocking
attribute_reference
denotes a generic unit
G, the reference shall occur within the
declarative region of
G.
Reason: We want the value of Nonblocking
attributes to be static so long as they occur outside of any generic
unit. The Nonblocking aspect of a generic unit will often depend on the
actual parameters of the unit, so it cannot be static (or have any well-defined
value). We need this latter rule in case the attribute of a generic is
used outside of the generic. Note that the previous rule makes it illegal
to use such an attribute to specify aspect Nonblocking outside of a generic,
but we don't want to allow any other uses since it does not have a known
value until instantiated.
Ramification: This rule does not apply
to instances of generic units and entities declared within them.
{
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 allows the use of the nonblocking
attribute of a generic formal type to describe whether these operations
of the type allow blocking.
Default initialization, finalization, and assignment
of elementary types are always nonblocking, so we don't need any rules
for those.
{
AI12-0064-2}
The predefined equality operator for a composite type is illegal if it
is nonblocking and, for a record type, it is not overridden by a primitive
equality operator, and:
for a record type, the parent primitive "="
allows blocking; or
any component that has a record type that has a
primitive "=" that allows blocking; or
any component that has a non-record type that 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.
{
AI12-0064-2}
In a generic instantiation (after replacement in the nonblocking expressions
by values of the actuals as described previously):
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 type corresponding to a nonblocking
formal private, derived, array, or access-to-subprogram type shall be
nonblocking;
Ramification: We do not require matching
for formal scalar or access-to-object types, as their predefined operators
are always nonblocking (and they re-emerge in the generic unit) —
the nonblocking status of the type has no impact.
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. In particular, these rules do
not apply when it specifies aspect Nonblocking to be an expression involving
attribute Nonblocking of a generic formal parameter. However, in such
a case, 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.
{
AI12-0064-2}
A program unit
P declared inside of a generic unit but not in
a generic body or that is a generic specification not declared in a generic
unit is considered nonblocking for the purposes of checking the restrictions
on a nonblocking unit only if the value of its Nonblocking aspect is
statically True. For the purposes of checks in
P, a call to a
subprogram is considered nonblocking unless the value of its Nonblocking
aspect is statically False.
Reason: This is a typical “assume-the-best”
rule. We only make checks if we know the nonblocking status of both P
and the called subprogram. All other checks will be performed when the
generic unit is instantiated. We used the awkward “inside of a
generic unit but not in a generic body” so that a generic specification
declared inside of a generic body uses the following “assume-the-worst”
rule.
{
AI12-0064-2}
A program unit
P declared inside of a generic body or that is
a generic body is considered nonblocking for the purposes of checking
the restrictions on a nonblocking unit unless the value of its Nonblocking
aspect is statically False. For the purposes of checks in
P, a
call to a subprogram is considered to allow blocking unless:
the value of its Nonblocking aspect is statically
True, or
its nonblocking expression (that is, Nonblocking
aspect) conforms exactly to that of P, or conforms to some part
of the nonblocking expression of P that is combined with the remainder
of the nonblocking expression of P by one or more and or
and then operations.
Ramification: That is, if the aspect
of the program unit is specified (directly or via inheritance) with any
non-static Nonblocking aspects, it is considered to be a nonblocking
program unit for the purposes of making checks. This is a typical “assume-the-worst”
rule.
Reason: The second part allows calls
on subprograms with Nonblocking aspects of Formal'Nonblocking, so long
as the Nonblocking aspect of P is some formula that contains Formal'Nonblocking
combined with and. This ensures that P will always allow blocking
if the actual for Formal turns out to allow blocking.
Without this rule,
we'd allow calls on formals in any body subprogram, even if the subprogram
did not include the formal in its Nonblocking aspect. For instance:
procedure Blah with Formal1'Blocking is
begin
Formal2;
end Blah;
If Formal1 is nonblocking and Formal2 allows
blocking, then we'd have a nonblocking routine calling a routine that
might block. That has to be prevented as this is “assume-the-worst”
checking.
To be honest: {
AI12-0319-1}
For checking in
P, default initialization, finalization, assignment,
or conversion to a formal subtype
F is considered to call subprograms
that have the nonblocking aspect of
F'Nonblocking, and this is
checked for conformance against that of
P as described above.
Note that the nonblocking aspect includes the evaluation of any predicate
for the subtype.
{
AI12-0319-1}
Similarly, for checking in
P, the implicit calls associated with
an
allocator
of an access type
A or a use of attribute
A'Storage_Size
are considered to call subprograms that have the nonblocking aspect of
A'Storage_Pool'Nonblocking, and this is checked for conformance
against that of
P as described above.
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-1}
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