9.10 Shared Variables
This Reference Manual output has not been verified, and may contain omissions or errors. Report any problems on the tracking issue
Static Semantics
1/5If 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.
Aspect_specification
s and representation items cannot change that fact. Note, however, that the components of an atomic object are not necessarily atomic. Dynamic Semantics
2/5[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;
- {8652/0031} 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
oraccept_statement
;
entry_index
of an accept_statement
is not synchronized with a corresponding entry call, nor is evaluating the entry barrier of an entry_body
. - If A1 is part of the execution of an
accept_statement
orentry_body
, and A2 is the action of returning from the corresponding entry call; 9 - 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 anentry_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
19/5The 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).
Wording Changes from Ada 95
Wording Changes from Ada 2005
Wording Changes from Ada 2012
9.10.1 Conflict Check Policies
1/5This subclause determines what checks are performed relating to possible concurrent conflicting actions (see 9.10).
Syntax
2/5The form of a pragma
Conflict_Check_Policy is as follows:
pragma Conflict_Check_Policy (policy_identifier
[, policy_identifier
]);
A pragma
Conflict_Check_Policy is allowed only immediately within a declarative_part
, a package_specification
, or as a configuration pragma.
Legality Rules
5/5Each policy_identifier
shall be one of No_Parallel_Conflict_Checks, Known_Parallel_Conflict_Checks, All_Parallel_Conflict_Checks, No_Tasking_Conflict_Checks, Known_Tasking_Conflict_Checks, All_Tasking_Conflict_Checks, No_Conflict_Checks, Known_Conflict_Checks, All_Conflict_Checks, or an implementation-defined conflict check policy. If two policy_identifier
s are given, one shall include the word Parallel and one shall include the word Tasking. If only one policy_identifier
is given, it shall not include the word Parallel or Tasking.
A pragma
Conflict_Check_Policy given in a declarative_part
or immediately within a package_specification
applies from the place of the pragma to the end of the innermost enclosing declarative region. The region for a pragma
Conflict_Check_Policy given as a configuration pragma is the declarative region for the entire compilation unit (or units) to which it applies.
If a pragma
Conflict_Check_Policy applies to a generic_instantiation
, then the pragma
Conflict_Check_Policy applies to the entire instance.
If multiple Conflict_Check_Policy pragmas apply to a given construct, the conflict check policy is determined by the one in the innermost enclosing region. If no Conflict_Check_Policy pragma applies to a construct, the policy is (All_Parallel_Conflict_Checks, No_Tasking_Conflict_Checks) (see below).
Certain potentially conflicting actions are disallowed according to which conflict check policies apply at the place where the action or actions occur, as follows:
No_Parallel_Conflict_Checks
- This policy imposes no restrictions on concurrent actions arising from parallel constructs.
No_Tasking_Conflict_Checks- This policy imposes no restrictions on concurrent actions arising from tasking constructs.
Known_Parallel_Conflict_Checks- If this policy applies to two concurrent actions appearing within parallel constructs, they are disallowed if they are known to denote the same object (see 6.4.1) with uses that conflict. For the purposes of this check, any parallel loop may be presumed to involve multiple concurrent iterations. Also, for the purposes of deciding whether two actions are concurrent, it is enough for the logical threads of control in which they occur to be concurrent at any point in their execution, unless all of the following are true:
- the shared object is volatile;
- the two logical threads of control are both known to also refer to a shared synchronized object; and
- each thread whose potentially conflicting action updates the shared volatile object, also updates this shared synchronized object.
Known_Tasking_Conflict_Checks
- If this policy applies to two concurrent actions appearing within the same compilation unit, at least one of which appears within a task body but not within a parallel construct, they are disallowed if they are known to denote the same object (see 6.4.1) with uses that conflict, and neither potentially signals the other (see 9.10). For the purposes of this check, any named task type may be presumed to have multiple instances. Also, for the purposes of deciding whether two actions are concurrent, it is enough for the tasks in which they occur to be concurrent at any point in their execution, unless all of the following are true:
- the shared object is volatile;
- the two tasks are both known to also refer to a shared synchronized object; and
- each task whose potentially conflicting action updates the shared volatile object, also updates this shared synchronized object.
All_Parallel_Conflict_Checks
- This policy includes the restrictions imposed by the Known_Parallel_Conflict_Checks policy, and in addition disallows a parallel construct from reading or updating a variable that is global to the construct, unless it is a synchronized object, or unless the construct is a parallel loop, and the global variable is a part of a component of an array denoted by an indexed component with at least one index expression that statically denotes the loop parameter of the
loop_parameter_specification
or the chunk parameter of the parallel loop. 21/5
All_Tasking_Conflict_Checks- This policy includes the restrictions imposed by the Known_Tasking_Conflict_Checks policy, and in addition disallows a task body from reading or updating a variable that is global to the task body, unless it is a synchronized object.
No_Conflict_Checks, Known_Conflict_Checks, All_Conflict_Checks- These are shorthands for (No_Parallel_Conflict_Checks, No_Tasking_Conflict_Checks), (Known_Parallel_Conflict_Checks, Known_Tasking_Conflict_Checks), and (All_Parallel_Conflict_Checks, All_Tasking_Conflict_Checks), respectively.
Static Semantics
23/5For a subprogram, the following language-defined representation aspect may be specified:
Parallel_Calls
- The Parallel_Calls aspect is of type Boolean. The specified value shall be static. The Parallel_Calls aspect of an inherited primitive subprogram is True if Parallel_Calls is True either for the corresponding subprogram of the progenitor type or for any other inherited subprogram that it overrides. If not specified or inherited as True, the Parallel_Calls aspect of a subprogram is False.
- Specifying the Parallel_Calls aspect to be True for a subprogram indicates that the subprogram can be safely called in parallel. Conflict checks (if required by the Conflict_Check_Policy in effect) are made on the subprogram assuming that multiple concurrent calls exist.[ Such checks can then be omitted on a call of the subprogram in a parallel iteration context.]
Implementation Permissions
26/5When the conflict check policy Known_Parallel_Conflict_Checks or All_Parallel_Conflict_Checks applies, the implementation may disallow two concurrent actions appearing within parallel constructs if the implementation can prove they will at run-time denote the same object with uses that conflict. Similarly, when the conflict check policy Known_Tasking_Conflict_Checks or All_Tasking_Conflict_Checks applies, the implementation may disallow two concurrent actions, at least one of which appears within a task body but not within a parallel construct, if the implementation can prove they will at run-time denote the same object with uses that conflict.