Ada Conformity Assessment Authority      Home Conformity Assessment   Test Suite ARGAda Standard
 
Annotated Ada Reference Manual (Ada 202x Draft 23)Legal Information
Contents   Index   References   Search   Previous   Next 

9.5.1 Protected Subprograms and Protected Actions

1
A protected subprogram is a subprogram declared immediately within a protected_definition. Protected procedures provide exclusive read-write access to the data of a protected object; protected functions provide concurrent read-only access to the data. 
1.a
Ramification: A subprogram declared immediately within a protected_body is not a protected subprogram; it is an intrinsic subprogram. See 6.3.1, “Conformance Rules”. 

Static Semantics

2
[Within the body of a protected function (or a function declared immediately within a protected_body), the current instance of the enclosing protected unit is defined to be a constant (that is, its subcomponents may be read but not updated). Within the body of a protected procedure (or a procedure declared immediately within a protected_body), and within an entry_body, the current instance is defined to be a variable (updating is permitted).]
2.a.1/3
Proof: {AI05-0120-1} All constant views are defined in 3.3, “Objects and Named Numbers”, anything not named there is a variable view. 
2.a
Ramification: The current instance is like an implicit parameter, of mode in for a protected function, and of mode in out for a protected procedure (or protected entry).
2.1/4
 {AI12-0129-1} For a type declared by a protected_type_declaration or for the anonymous type of an object declared by a single_protected_declaration, the following language-defined type-related representation aspect may be specified:
2.2/4
 Exclusive_Functions

The type of aspect Exclusive_Functions is Boolean. If not specified (including by inheritance), the aspect is False.
2.3/4
 
A value of True for this aspect indicates that protected functions behave in the same way as protected procedures with respect to mutual exclusion and queue servicing (see below).
2.a.1/4
Aspect Description for Exclusive_Functions: Specifies mutual exclusion behavior of protected functions in a protected type.
2.4/4
 {AI12-0129-1} A protected procedure or entry is an exclusive protected operation. A protected function of a protected type P is an exclusive protected operation if the Exclusive_Functions aspect of P is True.

Dynamic Semantics

3
For the execution of a call on a protected subprogram, the evaluation of the name or prefix and of the parameter associations, and any assigning back of in out or out parameters, proceeds as for a normal subprogram call (see 6.4). If the call is an internal call (see 9.5), the body of the subprogram is executed as for a normal subprogram call. If the call is an external call, then the body of the subprogram is executed as part of a new protected action on the target protected object; the protected action completes after the body of the subprogram is executed. [A protected action can also be started by an entry call (see 9.5.3).]
4/4
{AI12-0129-1} A new protected action is not started on a protected object while another protected action on the same protected object is underway, unless both actions are the result of a call on a nonexclusive protected function. This rule is expressible in terms of the execution resource associated with the protected object: 
5/4
{AI12-0129-1} Starting a protected action on a protected object corresponds to acquiring the execution resource associated with the protected object, either for exclusive read-write concurrent read-only access if the protected action is for a call on an exclusive protected operation a protected function, or for concurrent read-only exclusive read-write access otherwise;
6
Completing the protected action corresponds to releasing the associated execution resource. 
7/4
{AI12-0129-1} [After performing an exclusive protected operation on a protected object other than a call on a protected function, but prior to completing the associated protected action, the entry queues (if any) of the protected object are serviced (see 9.5.3).]
7.1/5
 {AI12-0119-1} If a parallel construct occurs within a protected action, no new logical threads of control are created. Instead, each element of the parallel construct that would have become a separate logical thread of control executes on the logical thread of control that is performing the protected action. If there are multiple such elements initiated at the same point, they execute in an arbitrary order.
7.a/5
Reason: It would be feasible to allow multiple logical threads of control within a protected action, but it would significantly complicate the definition of “sequential” and “concurrent” actions, since we generally presume that everything occuring within protected actions of a given protected object is sequential. We could simply disallow any use of parallel constructs, but that seems unnecessary, particularly as a parallel construct might be buried within a subprogram that is declared Nonblocking. 

Bounded (Run-Time) Errors

8/5
{AI12-0064-2} During a protected action, it is a bounded error to invoke an operation that is potentially blocking (see 9.5). potentially blocking. The following are defined to be potentially blocking operations: 
Paragraphs 9 through 16 were moved to 9.5.
8.a/5
Reason: {AI12-0064-2} Some of these operations are not directly blocking. However, they are still treated as bounded errors during a protected action, because allowing them might impose an undesirable implementation burden. 
9/5
a select_statement;
10/5
an accept_statement;
11/5
an entry_call_statement;
12/5
a delay_statement;
13/5
an abort_statement;
14/5
task creation or activation;
15/5
an external call on a protected subprogram (or an external requeue) with the same target object as that of the protected action; 
15.a/5
Reason: This is really a deadlocking call, rather than a blocking call, but we include it in this list for simplicity. 
16/5
a call on a subprogram whose body contains a potentially blocking operation. 
16.a/5
Reason: This allows an implementation to check and raise Program_Error as soon as a subprogram is called, rather than waiting to find out whether it actually reaches the potentially blocking operation. This in turn allows the potentially blocking operation check to be performed prior to run time in some environments.
17
If the bounded error is detected, Program_Error is raised. If not detected, the bounded error might result in deadlock or a (nested) protected action on the same target object.
17.a/2
Discussion: {AI95-00305-01} By “nested protected action”, we mean that an additional protected action can be started by another task on the same protected object. This means that mutual exclusion may be broken in this bounded error case. A way to ensure that this does not happen is to use pragma Detect_Blocking (see H.5). 
18/5
{AI12-0064-2} {AI12-0247-1} During a protected action, a call on a subprogram whose body contains a potentially blocking operation is a bounded error. If the bounded error is detected, Program_Error is raised; otherwise, the call proceeds normally. Certain language-defined subprograms are potentially blocking. In particular, the subprograms of the language-defined input-output packages that manipulate files (implicitly or explicitly) are potentially blocking. Other potentially blocking subprograms are identified where they are defined. When not specified as potentially blocking, a language-defined subprogram is nonblocking.
18.a/5
Discussion: {AI95-00178-01} Any subprogram in a language-defined input-output package that has a file parameter or result or operates on a default file is considered to manipulate a file. An instance of a language-defined input-output generic package provides subprograms that are covered by this rule. The only subprograms in language-defined input-output packages not covered by this rule (and thus not potentially blocking) are the Get and Put routines that take string parameters defined in the packages nested in Text_IO. 
18.b/5
Reason: {AI12-0247-1} This allows an implementation to check and raise Program_Error as soon as a subprogram is called, rather than waiting to find out whether it actually reaches the potentially blocking operation. If the call proceeds normally, reaching the potentially blocking operation is a separate bounded error, covered by the previous rules. 
NOTES
19/5
19  {AI12-0276-1} If two tasks both try to start a protected action on a protected object, and at most one is calling a protected nonexclusive function, then only one of the tasks can proceed. Although the other task cannot proceed, it is not considered blocked, and it might be consuming processing resources while it awaits its turn. Unless there is an admission policy (see D.4.1) in effect, there There is no language-defined ordering or queuing presumed for tasks competing to start a protected action — on a multiprocessor such tasks might use busy-waiting; for further monoprocessor and multiprocessor considerations, see D.3, “Priority Ceiling Locking”. 
19.a
Discussion: The intended implementation on a multi-processor is in terms of “spin locks” — the waiting task will spin. 
20
20  The body of a protected unit may contain declarations and bodies for local subprograms. These are not visible outside the protected unit.
21
21  The body of a protected function can contain internal calls on other protected functions, but not protected procedures, because the current instance is a constant. On the other hand, the body of a protected procedure can contain internal calls on both protected functions and procedures.
22
22  From within a protected action, an internal call on a protected subprogram, or an external call on a protected subprogram with a different target object is not considered a potentially blocking operation. 
22.a
Reason: This is because a task is not considered blocked while attempting to acquire the execution resource associated with a protected object. The acquisition of such a resource is rather considered part of the normal competition for execution resources between the various tasks that are ready. External calls that turn out to be on the same target object are considered potentially blocking, since they can deadlock the task indefinitely. 
23/5
23  {AI95-00305-01} {AI12-0064-2} The aspect Nonblocking can be specified True on the definition of a protected unit in order to reject most attempts to use potentially blocking operations within the protected unit (see 9.5). The pragma Detect_Blocking may be used to ensure that any remaining all executions of potentially blocking operations during a protected action raise Program_Error. See H.5
23.a/5
Discussion: {AI12-0064-2} The deadlock case cannot be detected at compile-time, so pragma Detect_Blocking is needed to give it consistent behavior.

Examples

24
Examples of protected subprogram calls (see 9.4): 
25
Shared_Array.Set_Component(N, E);
E := Shared_Array.Component(M);
Control.Release;

Wording Changes from Ada 95

25.a/2
{AI95-00305-01} Added a note pointing out the existence of pragma Detect_Blocking. This pragma can be used to ensure portable (somewhat pessimistic) behavior of protected actions by converting the Bounded Error into a required check. 

Extensions to Ada 2012

25.b/4
{AI12-0129-1} Corrigendum: Aspect Exclusive_Functions is new. The term “exclusive protected operations” is new. 

Wording Changes from Ada 2012

25.c/5
{AI12-0064-2} Moved the definition of potentially blocking operations to 9.5, so it could be integrated into the definition of the Nonblocking aspect.
25.d/5
{AI12-0247-1} Correction: Added a separate bounded error for a subprogram containing a blocking operation, to keep compatibility with Ada 95 rules without requiring a correct implementation of pragma Detect_Blocking to do full program analysis. 

Contents   Index   References   Search   Previous   Next 
Ada-Europe Ada 2005 and 2012 Editions sponsored in part by Ada-Europe