Contents Index Search 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_part]
is 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_clause representation_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_clause representation_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
- The values of the components of the
protected object, including (implicitly) an entry queue for each entry
declared for the protected object;
17.a
Ramification: "For
each entry" implies one queue for each single entry, plus one for
each entry of each entry family.
18
- {execution resource
(associated with a protected object) [partial]} A
representation of the state of the execution resource associated
with the protected object (one such resource is associated with each
protected object).
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.
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 Search Previous Next Legal