Contents   Index   Previous   Next


9.4 Protected Units and Protected Objects

1
   {protected object} {protected operation} {protected subprogram} {protected entry} A protected object provides coordinated access to shared data, through calls on its visible protected operations, which can be protected subprograms or protected entries. {protected declaration} {protected unit} {protected declaration} A protected unit is declared by a protected declaration, which has a corresponding protected_body. A protected declaration may be a protected_type_declaration, in which case it declares a named protected type; alternatively, it may be a single_protected_declaration, in which case it defines an anonymous protected type, as well as declaring a named protected object of that type. {broadcast signal: See protected object}

Syntax

2
protected_type_declaration ::=
  protected type defining_identifier [known_discriminant_partis protected_definition;
3
single_protected_declaration ::=
  protected defining_identifier is protected_definition;
4
protected_definition ::=
    { protected_operation_declaration }
private
    { protected_element_declaration } ]
  end [protected_identifier]
5/1
{8652/0009} protected_operation_declaration ::= subprogram_declaration
     | entry_declaration
     | aspect_clauserepresentation_clause
6
protected_element_declaration ::= protected_operation_declaration
     | component_declaration
6.a
Reason: We allow the operations and components to be mixed because that's how other things work (for example, package declarations). We have relaxed the ordering rules for the items inside declarative_parts and task_definitions as well.
7
protected_body ::=
  protected body defining_identifier is
   { protected_operation_item }
  end [protected_identifier];
8/1
{8652/0009} protected_operation_item ::= subprogram_declaration
     | subprogram_body
     | entry_body
     | aspect_clauserepresentation_clause
9
If a protected_identifier appears at the end of a protected_definition or protected_body, it shall repeat the defining_identifier.

Legality Rules

10
    {requires a completion (protected_declaration}) [partial]} A protected declaration requires a completion[, which shall be a protected_body,] and every protected_body shall be the completion of some protected declaration.
10.a
To be honest: The completion can be a pragma Import, if the implementation supports it.

Static Semantics

11
    A protected_definition defines a protected type and its first subtype. {visible part (of a protected unit) [partial]} The list of protected_operation_declarations of a protected_definition, together with the known_discriminant_part, if any, is called the visible part of the protected unit. [{private part (of a protected unit) [partial]} The optional list of protected_element_declarations after the reserved word private is called the private part of the protected unit.]
11.a
Proof: Private part is defined in Section 8.

Dynamic Semantics

12
    [{elaboration (protected declaration) [partial]} The elaboration of a protected declaration elaborates the protected_definition. {elaboration (single_protected_declaration) [partial]} The elaboration of a single_protected_declaration also creates an object of an (anonymous) protected type.]
12.a
Proof: This is redundant with the general rules for the elaboration of a full_type_declaration and an object_declaration.
13
    {elaboration (protected_definition) [partial]} [The elaboration of a protected_definition creates the protected type and its first subtype;] it also includes the elaboration of the component_declarations and protected_operation_declarations in the given order.
14
    [{initialization (of a protected object) [partial]} As part of the initialization of a protected object, any per-object constraints (see 3.8) are elaborated.]
14.a
Discussion: We do not mention pragmas since each pragma has its own elaboration rules.
15
    {elaboration (protected_body) [partial]} The elaboration of a protected_body has no other effect than to establish that protected operations of the type can from then on be called without failing the Elaboration_Check.
16
    The content of an object of a given protected type includes:
17
17.a
Ramification: "For each entry" implies one queue for each single entry, plus one for each entry of each entry family.
18
19
    [The execution resource associated with a protected object has to be acquired to read or update any components of the protected object; it can be acquired (as part of a protected action -- see 9.5.1) either for concurrent read-only access, or for exclusive read-write access.]
20
    {finalization (of a protected object) [partial]} {Program_Error (raised by failure of run-time check)} As the first step of the finalization of a protected object, each call remaining on any entry queue of the object is removed from its queue and Program_Error is raised at the place of the corresponding entry_call_statement.
20.a
Reason: This is analogous to the raising of Tasking_Error in callers of a task that completes before accepting the calls. This situation can only occur due to a requeue (ignoring premature unchecked_deallocation), since any task that has accessibility to a protected object is awaited before finalizing the protected object. For example:
20.b
procedure Main is
    task T is
        entry E;
    end T;
20.c
    task body T is
        protected PO is
            entry Ee;
        end PO;
20.d
        protected body PO is
            entry Ee when False is
            begin
                null;
            end Ee;
        end PO;
    begin
        accept E do
            requeue PO.Ee;
        end E;
    end T;
begin
    T.E;
end Main;
20.e
The environment task is queued on PO.EE when PO is finalized.
20.f
In a real example, a server task might park callers on a local protected object for some useful purpose, so we didn't want to disallow this case.
NOTES
21
13  Within the declaration or body of a protected unit, the name of the protected unit denotes the current instance of the unit (see 8.6), rather than the first subtype of the corresponding protected type (and thus the name cannot be used as a subtype_mark).
21.a
Discussion: However, it is possible to refer to some other subtype of the protected type within its body, presuming such a subtype has been declared between the protected_type_declaration and the protected_body.
22
14  A selected_component can be used to denote a discriminant of a protected object (see 4.1.3). Within a protected unit, the name of a discriminant of the protected type denotes the corresponding discriminant of the current instance of the unit.
23
15  A protected type is a limited type (see 7.5), and hence has neither an assignment operation nor predefined equality operators.
24
16  The bodies of the protected operations given in the protected_body define the actions that take place upon calls to the protected operations.
25
17  The declarations in the private part are only visible within the private part and the body of the protected unit.
25.a
Reason: Component_declarations are disallowed in a protected_body because, for efficiency, we wish to allow the compiler to determine the size of protected objects (when not dynamic); the compiler cannot necessarily see the body. Furthermore, the semantics of initialization of such objects would be problematic -- we do not wish to give protected objects complex initialization semantics similar to task activation.
25.b
The same applies to entry_declarations, since an entry involves an implicit component -- the entry queue.

Examples

26
    Example of declaration of protected type and corresponding body:
27
protected type Resource is
   entry Seize;
   procedure Release;
private
   Busy : Boolean := False;
end Resource;
28
protected body Resource is
   entry Seize when not Busy is
   begin
      Busy := True;
   end Seize;
29
   procedure Release is
   begin
      Busy := False;
   end Release;
end Resource;
30
    Example of a single protected declaration and corresponding body:
31
protected Shared_Array is
   --  Index, Item, and Item_Array are global types
   function  Component    (N : in Index) return Item;
   procedure Set_Component(N : in Index; E : in  Item);
private
   Table : Item_Array(Index) := (others => Null_Item);
end Shared_Array;
32
protected body Shared_Array is
   function Component(N : in Index) return Item is
   begin
      return Table(N);
   end Component;
33
   procedure Set_Component(N : in Index; E : in Item) is
   begin
      Table(N) := E;
   end Set_Component;
end Shared_Array;
34
    Examples of protected objects:
35
Control  : Resource;
Flags    : array(1 .. 100) of Resource;

Extensions to Ada 83

35.a
{extensions to Ada 83} This entire clause is new; protected units do not exist in Ada 83.

Contents   Index   Previous   Next   Legal