9.10 Shared Variables
Static Semantics
If two different
objects, including nonoverlapping parts of the same object, are
independently
addressable, they can be manipulated concurrently by two different
logical threads of control without synchronization, unless both are subcomponents
of the same full access object, and either is nonatomic (see
C.6).
Any two nonoverlapping objects are independently addressable if either
object is specified as independently addressable (see
C.6).
Otherwise, two nonoverlapping objects are independently addressable except
when they are both parts of a composite object for which a nonconfirming
value is specified for any of the following representation aspects: (record)
Layout, Component_Size, Pack, Atomic, or Convention; in this case it
is unspecified whether the parts are independently addressable.
Dynamic Semantics
Separate logical threads
of control normally proceed independently and concurrently with one another.
However, task interactions can be used to synchronize the actions of
two or more logical threads of control to allow, for example, meaningful
communication by the direct updating and reading of variables shared
between them. The actions of two different logical threads of control
are synchronized in this sense when an action of one
signals an
action of the other;
an action A1 is defined to signal
an action A2 under the following circumstances:
If A1 and A2 are part of the execution of the same
task, and the language rules require A1 to be performed before A2;
If A1 is the action of an activator that initiates
the activation of a task, and A2 is part of the execution of the task
that is activated;
If A1 is part of the activation of a task, and
A2 is the action of waiting for completion of the activation;
If A1 is part of the execution of a task, and A2
is the action of waiting for the termination of the task;
If A1 is the termination of a task T, and A2 is
either an evaluation of the expression T'Terminated that results in True,
or a call to Ada.Task_Identification.Is_Terminated with an actual parameter
that identifies T and a result of True (see
C.7.1);
If A1 is the action of issuing an entry call, and
A2 is part of the corresponding execution of the appropriate
entry_body
or
accept_statement;
If A1 is part of the execution of an
accept_statement
or
entry_body,
and A2 is the action of returning from the corresponding entry call;
If A1 is part of the execution of a protected procedure
body or
entry_body
for a given protected object, and A2 is part of a later execution of
an
entry_body
for the same protected object;
If A1 signals some
action that in turn signals A2.
Action A1 is defined to
potentially signal
action A2 if A1 signals A2, if action A1 and A2 occur as part of the
execution of the same logical thread of control, and the language rules
permit action A1 to precede action A2, or if action A1 potentially signals
some action that in turn potentially signals A2.
Two
actions are defined to be
sequential if one of the following is
true:
One action signals the other;
Both actions occur as part of the execution of
the same logical thread of control;
Both actions occur as part of protected actions
on the same protected object, and at least one of the actions is part
of a call on an exclusive protected operation of the protected object.
Aspect Atomic or aspect Atomic_Components may also
be specified to ensure that certain reads and updates are sequential
— see
C.6.
Two actions that are not sequential are defined to
be
concurrent actions.
Two actions are defined to
conflict if one
action
assigns to an object,
and the other action reads or assigns to a part of the same object (or
of a neighboring object if the two are not independently addressable).
The action comprising a call on a subprogram or an entry is defined to
potentially conflict with another action if the Global aspect
(or Global'Class aspect in the case of a dispatching call) of the called
subprogram or entry is such that a conflicting action
would be possible during the execution of the call. Similarly, two calls
are considered to potentially conflict if they each have Global (or Global'Class
in the case of a dispatching call) aspects such that conflicting actions
would be possible during the execution of the calls. Finally, two actions
that conflict are also considered to potentially conflict.
A
synchronized object
is an object of a task or protected type, an atomic object (see
C.6),
a suspension object (see
D.10), or a synchronous
barrier (see
D.10.1). Operations on such
objects are necessarily sequential with respect to one another, and hence
are never considered to conflict.
Erroneous Execution
The execution of two concurrent actions is erroneous
if the actions make conflicting uses of a shared variable (or neighboring
variables that are not independently addressable).
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe