Ada 95 Protected Objects for Synchronizing Shared Data Structures

54
Currie Colket The MITRE Corporation Phone: (703) 883-7381 Email: [email protected] | [email protected] DC SIGAda 14 March 2002 SIGAda Home Page http://www.acm.org/sigada Acknowledgement and Thanks to Bill Thomas for his help and ideas. Ada 95 Protected Objects for Synchronizing Shared Data Structures

description

Ada 95 Protected Objects for Synchronizing Shared Data Structures. Currie Colket The MITRE Corporation Phone: (703) 883-7381 Email: [email protected] | [email protected] DC SIGAda 14 March 2002. SIGAda Home Page  http://www.acm.org/sigada. - PowerPoint PPT Presentation

Transcript of Ada 95 Protected Objects for Synchronizing Shared Data Structures

Page 1: Ada 95 Protected Objects for Synchronizing Shared Data Structures

Currie ColketThe MITRE Corporation

Phone: (703) 883-7381Email: [email protected] | [email protected]

DC SIGAda14 March 2002

SIGAda Home Page http://www.acm.org/sigada

Acknowledgement and Thanks to Bill Thomas for his help and ideas.

Ada 95 Protected Objects for Synchronizing Shared Data Structures

Page 2: Ada 95 Protected Objects for Synchronizing Shared Data Structures

2

So What Are Protected Objects?

Page 3: Ada 95 Protected Objects for Synchronizing Shared Data Structures

3

Overview

Introduction Features that Make Protected Objects Attractive Ada 95 RM View of Protected Objects Designing Software With Protected Objects

- Design Considerations

- Ada 95 Quality and Style Guide

- Guide for the Use of the Ada Programming Language in High Integrity Systems (ISO TR 15942)

Automatic Analysis of Protected Objects Using ASIS Conclusion

Page 4: Ada 95 Protected Objects for Synchronizing Shared Data Structures

4

Motivation For Protected Object - 1

package Protected_Position is procedure Read (X: out Position); procedure Write (X: in Position);end Protected_Position;package body Protected_Position is Protected_Object: Position := (0.0,0.0); procedure Read (X: out Position) is begin X := Protected_Object; end Read; procedure Write (X: in Position) is begin Protected_Object := X; end Write;end Protected_Position;

type Position is record Latitude: Float; Longitude: Float; end record;

Consider:

And the effects of

Time Slicing

Expiration of a delay of a higher priority task

Page 5: Ada 95 Protected Objects for Synchronizing Shared Data Structures

5

Motivation For Protected Object - 2

type Position is record Latitude: Float; Longitude: Float; end record;

Still:

protected Protected_Position is procedure Read (X: out Position); procedure Write (X: in Position);private Protected_Object: Position := (0.0,0.0);end Protected_Position; protected body Protected_Position is

procedure Read (X: out Position) is begin X := Protected_Object; end Read; procedure Write (X: in Position) is begin Protected_Object := X; end Write;end Protected_Position;

With Mutual Exclusion

Page 6: Ada 95 Protected Objects for Synchronizing Shared Data Structures

6

IntroductionProtected ObjectsProtected objects provide• coordinated access to shared data

- through calls on its visible protected operations, Protected Operations can be• Protected subprograms or • Protected entries. Protected units are declared by a • Protected declaration, and• Corresponding protected_body. Protected declaration may be a • Protected_type_declaration

- in which case it declares a named protected type;• Single_protected_declaration

- in which case it defines an anonymous protected type,- as well as declaring a named protected object of that type

Every Protected DeclarationRequired a Protected Body

Page 7: Ada 95 Protected Objects for Synchronizing Shared Data Structures

7

Features That Make Protected Objects Attractive as a Building Block - 1

Scalability - Synchronization mechanism scales smoothly from a single processor to a multiprocessor. Adaptability - Additional protected operations may be added to a protected type without the need to modify the existing specification (e.g., use explicit signals and explicitly signal all possible waiting tasks.) Modularity - All of the operations of a given critical region are identified in the specification, and the operationss are encapsulated within the body. The protected data is encapsulated within the private part. Efficiency - Size and initialization requirements are known at compile time, because all entries and data components are declared in the specification. • Allocated statically (directly on the stack) rather than via dynamic allocation• No extra context switches are required to service waiting clients (since task changing state may directly execute entry bodies whose barriers become true)• Non-queued locking may be used to implement mutual exclusion of a protected object because no blocking is permitted during the execution of a protected operation.

Page 8: Ada 95 Protected Objects for Synchronizing Shared Data Structures

8

Features That Make Protected Objects Attractive as a Building Block - 2

Expressiveness - Explicit distinctions between read-only operations (functions), read-write operations (procedures), and possibly blocking operations (entries). This distinction is vital in analyzing a real-time program for correctness, including freedom from deadlock.

Compatibility – Compatible with Ada95 tasking.

Interrupt Handling - Well suited to act as an interrupt handler for a number of reasons; they both typically have a short bounded execution time, do not arbitrarily block, have a limited context and finally they both have to integrate with the priority model. The nonblocking critical region matches the needs of an interrupt handler, as well as the needs of non-interrupt-level code to synchronize with an interrupt handler. The entry barrier construct allows an interrupt handler to signal a normal task by changing the state of a component of the protected object and thereby making a barrier true.

Page 9: Ada 95 Protected Objects for Synchronizing Shared Data Structures

9

IntroductionSimple Example of Protected Objects

protected Counter is procedure Increment (New_Value: out Positive); function Get_Counter return Integer; private Data: Integer := 0; end Counter;

protected body Counter is procedure Increment (New_Value: out Positive) is begin Data := Data + 1; New_Value := Data; end Increment; function Get_Counter is begin return Data; end Get_Counter; end Counter;

Counter

Task may increment it by:

Counter.Increment (New_Value => X);

Task may obtain the Counter value by:

A := Counter.Get_Counter;

Page 10: Ada 95 Protected Objects for Synchronizing Shared Data Structures

10

Ada 95 RM Protected Objects

3.X Declarations and Types

9.0 Tasks and Synchronization

9.4 Protected Units and Protected Objects

9.5 Intertask Communication

.1 Protected Subprograms and Protected Actions

.2 Entries and Accept Statements

.3 Entry Calls

.4 Requeue

9.8 Abort

9.9 Task and Entry Attributes

10.1.3 Progrm Structure and Compilation Issues

C.6 Shared Variable Control

Page 11: Ada 95 Protected Objects for Synchronizing Shared Data Structures

11

Ada 95 RM 3.0 Declarations and Types (Miscellaneous Syntax)

full_type_declaration::= type defining_identifier [known_discriminant_part] is type_definition; | task_type_declaration | protected_type_declaration

object_declaration::= defining_identifier_list : [aliased] [constant] subtype_indication [:= expression]; | defining_identifier_list : [aliased] [constant] array_type_definition [:= expression]; | single_task_declaration | single_protected_declaration

access_to_subprogram_definition::= access [protected] procedure parameter_profile | access [protected] function parameter_and_result_profile

proper_body::= subprogram_body | package_body | task_body | protected_body

Ada LRM 3.2.1

Ada LRM 3.10

Ada LRM 3.3.1

Ada LRM 3.11

Page 12: Ada 95 Protected Objects for Synchronizing Shared Data Structures

12

Ada 95 RM 9.4 Protected Units and Protected Objects - 1

single_protected_declaration ::=

protected defining_identifier is protected_definition;

protected_type_declaration ::=

protected type defining_identifier [known_discriminant_part] is protected_definition;

protected_definition ::=

{ protected_operation_declaration }

[ private

{ protected_element_declaration } ]

end [protected_identifier]

Visible Part of the Protected Unit

Private Part of the Protected Unit

Page 13: Ada 95 Protected Objects for Synchronizing Shared Data Structures

13

Ada 95 RM 9.4 Protected Units and Protected Objects

protected_operation_declaration ::=

subprogram_declaration | entry_declaration | aspect_clause

protected_element_declaration ::= protected_operation_declaration | component_declaration

protected_body ::=

protected body defining_identifier is

{ protected_operation_item }

end [protected_identifier];

protected_operation_item ::= subprogram_declaration

| subprogram_body | entry_body | aspect_clause

aspect_clause: Chapter 13

Protected_body from Chapter 10

Page 14: Ada 95 Protected Objects for Synchronizing Shared Data Structures

14

Ada 95 RM Example of Declaration of Protected Type

protected type Resource is entry Seize; procedure Release; private Busy : Boolean := False; end Resource;

protected body Resource is entry Seize when not Busy is begin Busy := True; end Seize; procedure Release is begin Busy := False; end Release; end Resource;

Examples of protected objects: Control : Resource; Flags : array (1 .. 4) of Resource;

Page 15: Ada 95 Protected Objects for Synchronizing Shared Data Structures

15

Ada 95 RM Example of Single Protected Declarationprotected Shared_Array is function Get_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;

protected body Shared_Array is function Get_Component(N : in Index) return Item is begin return Table(N); end Get_Component; procedure Set_Component(N : in Index; E : in Item) is begin Table(N) := E; end Set_Component;end Shared_Array;

Note: Index, Item, &Item_Arrayare global types

Examples:Shared_Array.Set_Component(N, E);E := Shared_Array. Get_Component(M);

Not allowed todeclare new objects

Page 16: Ada 95 Protected Objects for Synchronizing Shared Data Structures

16

Ada 95 RM 9.4 Protected Units and Protected Objects

9.4 Notes•A protected type is a limited type and hence has neither an assignment operation nor predefined equality operators.•The bodies of the protected operations given in the protected_body define the actions that take place upon calls to the protected operations.•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.

Page 17: Ada 95 Protected Objects for Synchronizing Shared Data Structures

17

Ada 95 RM 9.5 Intertask Communications - 1

Primary means for Intertask Communication is provided by • Calls on Entries and • Calls on Protected Subprograms.

Calls on protected subprograms allow coordinated access to shared data objects.

Entry calls allow for blocking the caller • Until a given condition is satisfied (e.g., entry is open), and • Then communicating data or control information - Directly with another task or - Indirectly via a shared protected object.

(for Protected Objects)

Page 18: Ada 95 Protected Objects for Synchronizing Shared Data Structures

18

Ada 95 RM 9.5 Intertask Communications - 2

Model: Entries always have barrier conditionsEggshell Model:

John Barnes wrote in describing the Eggshell Model: “It must be understood that the barrier protection mechanism is superimposed upon the natural mutual exclusion of the protected construct thus giving two distinct levels of protection”

Get_Item

Set_Item

Tasks waiting on barrier(in entry queues)

Task executing(at most one)

Tasks outside(in unstructured way)

Guard

Page 19: Ada 95 Protected Objects for Synchronizing Shared Data Structures

19

Ada 95 RM 9.5 Intertask Communications - 3

Renamings allowed

Page 20: Ada 95 Protected Objects for Synchronizing Shared Data Structures

20

Ada 95 RM 9.5.1 Protected Subprograms and Protected Actions - 1

Protected Subprogram • Subprograms 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

Resource

Blocked/Not-Blocked

Function Call Procedure Call

For proceduresBlocked If functionsaccessing

For functionsBlockedIf procedureaccessingNot really called blocked

Page 21: Ada 95 Protected Objects for Synchronizing Shared Data Structures

21

Ada 95 RM 9.5.1 Protected Subprograms and Protected Actions - 2

Bounded (Run-Time) Errors: During a protected action, it is a bounded error to invoke an operation that is potentially blocking.

Potentially blocking operations:

a select_statement; an accept_statement; an entry_call_statement; a delay_statement; an abort_statement; task creation or activation; an external call on a protected subprogram (or an external requeue) with the same target object as that of the protected action; a call on a subprogram whose body contains a potentially blocking operation (especially I/O).

If the bounded error is detected Program_Error is raisedelse Bounded error might result in deadlock or a (nested) protected action on the same target object.

Page 22: Ada 95 Protected Objects for Synchronizing Shared Data Structures

22

Ada 95 RM 9.5.1 Protected Subprograms and Protected Actions - 3

Notes for 9.5.1:• If two tasks both try to start a protected action on a protected object, and at most one is calling a protected function, then only one task 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. • There is no language-defined ordering or queuing presumed for tasks competing to start a protected action • Priority Ceiling Locking is possible with pragma Locking_Policy (See D.3)• Body of a protected function can contain internal calls on other protected functions, but not protected procedures• Body of a protected procedure can contain internal calls on both protected functions and procedures. • 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.

Page 23: Ada 95 Protected Objects for Synchronizing Shared Data Structures

23

Ada 95 RM 9.5.2 Entries and Accept Statements - 1

entry_declaration ::= entry defining_identifier [(discrete_subtype_definition)] parameter_profile;

entry_body ::= entry defining_identifier entry_body_formal_part entry_barrier is declarative_part begin handled_sequence_of_statements end [entry_identifier]; entry_body_formal_part ::= [(entry_index_specification)] parameter_profile

entry_barrier ::= when condition

entry_index_specification ::= for defining_identifier in discrete_subtype_definition

Entry_declarations, with the corresponding entry_bodies are used to define potentially queued operations on protected objects.

Entry_declarations are only allowed fortask declarations and protected declarations.

Condition for entry_barrier can be any private or global data except for the object of the parameter_profile - Index & Discriminant OK

Note barrier is requiredNote barrier is required

Page 24: Ada 95 Protected Objects for Synchronizing Shared Data Structures

24

Ada 95 RM 9.5.2 Entries and Accept Statements - 2

Notes:• parameter modes are the same as for a subprogram_declaration and have the same meaning • An entry_declaration with a discrete_subtype_definition declares a family of distinct entries having the same profile.• An entry_body is executed when the condition of the entry_barrier evaluates to True and a caller of the corresponding single entry, or entry of the corresponding entry family, has been selected• A task entry has 0 or more corresponding accept_statements; a protected entry has exactly one corresponding entry_body.• A return_statement or a requeue_statement may be used to complete the execution of an entry_body.

Page 25: Ada 95 Protected Objects for Synchronizing Shared Data Structures

25

Ada 95 RM 9.5.3 Entry Calls - 1

entry_call_statement ::= entry_name [actual_parameter_part];

For: Device : array(1 .. 4) of Resource;Device(3).Seize;

protected body Resource is entry Seize when not Busy is begin Busy := True; end Seize; procedure Release is begin Busy := False; end Release; end Resource;

Resource 1

Guardnot Busy

Queue

Resource 2

Guardnot Busy

Queue

Resource 3

Guardnot Busy

Queue

Resource 4

Guardnot Busy

Queue

Page 26: Ada 95 Protected Objects for Synchronizing Shared Data Structures

26

Ada 95 RM 9.5.3 Entry Calls - 2 Notes:

An entry of a protected object is open if the condition of the entry_barrier of the corresponding entry_body evaluates to True; otherwise it is closed. • If open, the entry call is said to be selected immediately, and the execution of the call proceeds with the entry_body• If closed, the entry call is added to an entry queue and the call remains queued until it is selected or cancelled; there is a separate (logical) entry queue for each entry family for protected object• If an exception is raised during the execution of an entry_body, it is propagated to the corresponding caller• If evaluation of barrier propagates an exception, Program_Error is propagated to all current callers of all entries of the protected object. • Entry Queuing Policies selected with pragma Queuing Policy (D.4)• Cancellation of a call on an entry of a protected object is a protected action, and as such cannot take place while any other protected action is occurring on the protected object. Like any protected action, it includes servicing of theentry queues (in case some entry barrier depends on a Count attribute).

Page 27: Ada 95 Protected Objects for Synchronizing Shared Data Structures

27

Ada 95 RM 9.5.4 Requeue Statement - 1

A requeue_statement can be used to complete an entry_body, while redirecting the corresponding entry call to a new (or the same) entry queue.

requeue_statement ::= requeue entry_name [with abort];

Notes: For the execution of a requeue on an entry of a target protected object, after leaving the enclosing callable construct: If the requeue is an internal requeue (that is, the requeue is back on an entry of the same protected object), the call is added to the queue of the named entry and the ongoing protected action continues; If the requeue is an external requeue (that is, the target protected object is not implicitly the same as the current object), a protected action is started on the target object and proceeds as for a normal entry call.

Page 28: Ada 95 Protected Objects for Synchronizing Shared Data Structures

28

Ada 95 RM 9.5.4 Requeue Statement - 2

Notes (continued):

• If the requeue_statement includes the reserved words with abort (it is arequeue-with-abort), then: - If the original entry call has been aborted, then the requeue acts as an abort completion point for the call, and the call is cancelled and no requeue is performed; - If the original entry call was timed (or conditional), then the original expiration time is the expiration time for the requeued call. • If the reserved words with abort do not appear, then the call remains protectedagainst cancellation while queued as the result of the requeue_statement.

Page 29: Ada 95 Protected Objects for Synchronizing Shared Data Structures

29

Ada 95 RM 9.8 Abort Statement

An abort_statement causes one or more tasks to become abnormal, thus

preventing any further interaction with such tasks.

When the execution of a construct is aborted (including that of a task_body or of a sequence_of_statements), the execution of every construct included within the aborted execution is also aborted, except for executions included within the execution of an abort-deferred operation; the execution of an abort-deferred operation continues to completion without being affected by the abort; the following are the abort-deferred operations:

a protected action; …

Abort takes place after the protected is completed.

Page 30: Ada 95 Protected Objects for Synchronizing Shared Data Structures

30

Ada 95 RM 9.9 Task and Entry Attributes

For a prefix E that denotes an entry of a task or protected unit:

E'Count

Yields the number of calls presently queued on the entry E of the current instance of the unit. The value of this attribute is of the type universal_integer.

Notes:

• This attribute is only allowed within the body of the task or protected unit.• Entry can be either a single entry or an entry of a family. • Within protected units, algorithms interrogating the attribute E'Count in the entry_barrier for the entry E should take precautions to allow for the evaluation of the condition of the barrier both before and after queuing a given caller.

Page 31: Ada 95 Protected Objects for Synchronizing Shared Data Structures

31

Ada 95 RM 10.1.3 Program Structure and Compilation Issues

body_stub::= subprogram_body_stub | package_body_stub | task_body_stub | protected_body_stub

protected_body_stub::= protected body defining_identifier is separate;

Page 32: Ada 95 Protected Objects for Synchronizing Shared Data Structures

32

Ada 95 RM C.6 Shared Variable Control

Clause specifies representation pragmas that control use of shared variables: pragma Atomic (local_name); pragma Volatile (local_name); pragma Atomic_Components (array_local_name); pragma Volatile_Components (array_local_name);

• For an atomic object (including an atomic component) all reads and updates of the object as a whole are indivisible.• For a volatile object all reads and updates of the object as a whole are performed directly to memory.• An imported volatile or atomic constant behaves as a constant (i.e. read-only) with respect to other parts of the Ada program, but can still be modified by an “external source.”It is illegal to apply pragma to an object or type if the implementation cannot support the indivisible reads and updates - Program Error

local_name denotes • object_declaration, • non-inherited component_declaration,• full_type_declaration. array_local_name denotes• declaration of an array type• array object of an anonymous type.

Page 33: Ada 95 Protected Objects for Synchronizing Shared Data Structures

33

Designing Software With Protected Objects Overview

Design Considerations

(Thoughts on Sharing Resources and Data on Design)

Ada 95 Quality and Style Guide Recommendations

Guide for the Use of the Ada Programming Language in High Integrity Systems (ISO TR 15942)

Page 34: Ada 95 Protected Objects for Synchronizing Shared Data Structures

34

Design Considerations Example 1: System Example

System Control

Navigation SensorControl Tracking Fire

Control

Radar Infra Red ESM Acoustics

...

...

How is Data Here?

Shared Here?

System Protected ObjectsSystem Devices (Resources)System Data (e.g., Own_Position)Distributed Environment(How many processors?)

Subsystem Protected ObjectsMultiple Subsystem TasksHow critical is timing of data

Page 35: Ada 95 Protected Objects for Synchronizing Shared Data Structures

35

Ada 95 Quality & Style Guide 3.2.7 Program Name Units

Guidelines: Use nouns descriptive of the data being protected for protected units.

Examples: protected Current_Location is -- data being protected protected type Guardian is -- noun implying protection

Rationale: Using these naming conventions creates understandable code that reads much like natural language. When verbs are used for actions, such as subprograms, and nouns are used for objects, such as the data that the subprogram manipulates, code is easier to read and understand.

Page 36: Ada 95 Protected Objects for Synchronizing Shared Data Structures

36

Ada 95 Quality & Style Guide 5.9.9 Programming Practices

Guidelines: Do not invoke a potentially blocking operation within a protected entry,

a protected procedure, or a protected function. Rationale: Blocking operations mentioned in Ada95 RM - Select statement - Accept statement - Entry-call statement - Delay statement - Abort statement - Task creation or activation - External call on a protected subprogram (or an external requeue) with the same target object as that of the protected action - Call on a subprogram whose body contains a potentially blocking operation Invoking any of these potentially blocking operations could lead either to a bounded error being detected or to a deadlock situation. In the case of bounded error, the exception Program_Error is raised. In addition, avoid calling routines within a protected entry, procedure, or function that could directly or indirectly invoke operating system primitives or similar operations that can cause blocking that is not visible to the Ada run-time system.

Page 37: Ada 95 Protected Objects for Synchronizing Shared Data Structures

37

Ada 95 Quality & Style Guide – Section 6.1.16.1 Concurrency Options; 6.1.1 Protected Objects 1

Guidelines: Consider using protected objects to provide mutually exclusive access to data. Consider using protected objects to control or synchronize access to data shared by multiple tasks. Consider using protected objects to implement synchronization, such as a passive resource monitor. Consider encapsulating protected objects in the private part or body of a package. Consider using a protected procedure to implement an interrupt handler. Do not attach a protected procedure handler to a hardware interrupt if that interrupt has a maximum priority greater than the ceiling priority assigned to the handler. Avoid the use of global variables in entry barriers. Avoid the use of barrier expressions with side effects.

Page 38: Ada 95 Protected Objects for Synchronizing Shared Data Structures

38

Ada 95 Quality & Style Guide – Section 6.1.16.1 Concurrency Options; 6.1.1 Protected Objects 2

Example: generic type Item is private; Maximum_Buffer_Size : in Positive; package Bounded_Buffer_Package is subtype Buffer_Index is Positive range 1..Maximum_Buffer_Size; subtype Buffer_Count is Natural range 0..Maximum_Buffer_Size; type Buffer_Array is array (Buffer_Index) of Item; protected type Bounded_Buffer is entry Get (X : out Item); entry Put (X : in Item); private Get_Index : Buffer_Index := 1; Put_Index : Buffer_Index := 1; Count : Buffer_Count := 0; Data : Buffer_Array; end Bounded_Buffer; end Bounded_Buffer_Package;

Page 39: Ada 95 Protected Objects for Synchronizing Shared Data Structures

39

Ada 95 Quality & Style Guide – Section 6.1.16.1 Concurrency Options; 6.1.1 Protected Objects 3

package body Bounded_Buffer_Package is Example (continued)protected body Bounded_Buffer is

entry Get (X : out Item) when Count > 0 is begin X := Data(Get_Index); Get_Index := (Get_Index mod Maximum_Buffer_Size) + 1; Count := Count - 1; end Get;

entry Put (X : in Item) when Count < Maximum_Buffer_Size is begin Data(Put_Index) := X; Put_Index := (Put_Index mod Maximum_Buffer_Size) + 1; Count := Count + 1; end Put;

end Bounded_Buffer; end Bounded_Buffer_Package;

Page 40: Ada 95 Protected Objects for Synchronizing Shared Data Structures

40

Ada 95 Quality & Style Guide – Section 6.1.16.1 Concurrency Options; 6.1.1 Protected Objects 4

Rationale:Protected objects are intended to provide a "lightweight" mechanism for mutual exclusion and data synchronization. You should use a task only when you need to introduce explicitly a new, concurrent thread of control (see Guideline 6.1.2). A protected procedure is very well suited to act as an interrupt handler for a number of reasons; they both typically have a short bounded execution time, do not arbitrarily block, have a limited context and finally they both have to integrate with the priority model. The nonblocking critical region matches the needs of an interrupt handler, as well as the needs of non-interrupt-level code to synchronize with an interrupt handler. The entry barrier construct allows an interrupt handler to signal a normal task by changing the state of a component of the protected object and thereby making a barrier true. A global variable could be changed by another task or even by a call of a protected function. These changes will not be acted upon promptly. Therefore, you should not use a global variable in an entry barrier.

Page 41: Ada 95 Protected Objects for Synchronizing Shared Data Structures

41

Ada 95 Quality & Style Guide 6.1.4 Anonymous Task Types and Protected Types

Guidelines: Consider using single protected declarations to declare unique instances of protected objects.Rationale: The use of anonymous protected objects of anonymous type avoids a proliferation of protected types that are only used once, and the practice communicates to maintainers that there are no other protected objects of that type. If the need arises later to have additional protected objects of the same type, then the work required to convert an anonymous anonymous protected object to a protected type is minimal. The consistent and logical use of protected types, contributes to understandability. Identical protected objects can be declared using a common protected type. Dynamically allocated protected structures are necessary when you must create and destroy protected objects dynamically or when you must reference them by different names. Huh?

Huh?

Huh?

Page 42: Ada 95 Protected Objects for Synchronizing Shared Data Structures

42

Ada 95 Quality & Style Guide6.1.8 Extensibility and Concurrent Structures - 1

Guidelines: Carefully consider the placement of components of protected types within a

tagged type inheritance hierarchy. Consider using generics to provide extensibility of data types requiring the restrictions provided by protected objects.

Rationale:• Once a component of a protected type is added to an inheritance hierarchy of an abstract data type, further extensibility of that data type is impaired. When you constrain the concurrent behavior of a type (i.e., introduce a protected type component), you lose the ability to modify that behavior in subsequent derivations. Therefore, when the need arises for a version of an abstract data type to impose the restrictions provided by protected objects, the opportunity for reuse is maximized by adding the protected objects at the leaves of the inheritance hierarchy. • The reusability of common protected operations (e.g., mutually exclusive read/write operations) can be maximized by using generic implementations of abstract data types. These generic implementations then provide templates that can be instantiated with data types specific to individual applications.

Huh?

Page 43: Ada 95 Protected Objects for Synchronizing Shared Data Structures

43

Ada 95 Quality & Style Guide6.1.8 Extensibility and Concurrent Structures - 2

Rationale (Continued):•The reusability of common protected operations (e.g., mutually exclusive read/write operations) can be maximized by using generic implementations of abstract data types. These generic implementations then provide templates that can be instantiated with data types specific to individual applications.•Note: You can address synchronization within an inheritance hierarchy: - You can declare the root as a limited tagged type with a component that belongs to a protected type and give the tagged type primitive operations that work by invoking the protected operations of that component.- Given a tagged type implementing an abstract data type (perhaps resulting from several extensions), you can declare a protected type with a component belonging to the tagged type. The body of each protected operation would then invoke the corresponding operation of the abstract data type. The protected operations provide mutual exclusion.- You can use a hybrid approach where you declare a protected type with a component of some tagged type. You then use this protected type to implement a new root tagged type (not a descendant of the original tagged type).

Page 44: Ada 95 Protected Objects for Synchronizing Shared Data Structures

44

Ada 95 Quality & Style Guide 6.2.3 Attributes 'Count, 'Callable, and 'Terminated

Guidelines: Do not depend on the values of the task attributes 'Callable or 'Terminated Do not depend on attributes to avoid Tasking_Error on an entry call. For tasks, do not depend on the value of the entry attribute 'Count. Using the 'Count attribute with protected entries is more reliable than using the 'Count attribute with task entries.Rationale: Attributes 'Callable, 'Terminated, and 'Count are all subject to race conditions. The value of the attribute 'Count is stable for protected units because any change to an entry queue is itself a protected action, which will not occur while any other protected action is already proceeding. Nevertheless, when you use 'Count within an entry barrier of a protected unit, you should remember that the condition of the barrier is evaluated both before and after queueing a given caller.

Page 45: Ada 95 Protected Objects for Synchronizing Shared Data Structures

45

Ada 95 Quality & Style Guide 6.2.4 Unprotected Shared Variables

Guidelines: Use calls on protected subprograms or entries to pass data between tasks rather than unprotected shared variables. Do not use unprotected shared variables as a task synchronization device. Do not reference nonlocal variables in a guard. If an unprotected sharing is necessary, use the pragma Volatile or Atomic.Examples: 2 examples of failure due to synchronization problems Printer Example - no synchronization or mutual exclusion between the task that reads a command and the one that acts on it Vending Machine Example - Guard is a global with no protectionRationale: There are many techniques for protecting and synchronizing data access. You must program most of them yourself to use them. It is difficult to write a program that shares unprotected data correctly. If it is not done correctly, the reliability of the program suffers.

Page 46: Ada 95 Protected Objects for Synchronizing Shared Data Structures

46

Ada 95 Quality & Style Guide 6.2.5 Selective Accepts and Entry Calls

Guidelines: Consider using protected objects instead of the rendezvous for

data-oriented synchronization.

Rationale: Protected objects offer an efficient means for providing data-oriented synchronization. Operations on protected objects incur less execution overhead than tasks and are more efficient for data synchronization and communication than the rendezvous.

Page 47: Ada 95 Protected Objects for Synchronizing Shared Data Structures

47

Ada 95 Quality & Style Guide - 7.0 Portability 7.4.7Unprotected Shared Variables and Pragmas Atomic and Volatile

Guidelines: Do not use unprotected shared variables. Consider using protected types to provide data synchronization. Do not use unprotected shared variables as a task synchronization device. Consider using protected objects to encapsulate shared data. Use pragma Atomic or Volatile only when you are forced to by run-time

system deficiencies.

Rationale: The rationale for this appears in Guidelines 6.1.1 and 6.2.4. In addition, the treatment of unprotected shared variables varies from implementation to implementation, thereby hindering portability.

Page 48: Ada 95 Protected Objects for Synchronizing Shared Data Structures

48

Ada 95 Quality & Style Guide 10.6.2 (Performance) Protected Types - 1

Guidelines: For mutual exclusion, when measured performance indicates, use protected types as an alternative to tasking rendezvous. To implement an interrupt handler, when performance measurement indicates, use a protected procedure.

Rationale: Protected objects are meant to be much faster than tasks used for the same purpose (see Guideline 6.1.1). Determine the impact of using protected objects to provide access safely to encapsulated data in a concurrent program.

Page 49: Ada 95 Protected Objects for Synchronizing Shared Data Structures

49

Ada 95 Quality & Style Guide 10.6.2 (Performance) Protected Types - 2

Example: protected Object is function Read return Float; procedure Write (Value : in Float); private Data : Float; end Object; protected body Object is function Read return Float is begin return Data; end Read; procedure Write (Value : in Float) is begin Data := Value; end Write; end Object; task type Modify is end Modify;

type Mod_Bunch is array (1 .. 5) of Modify; task body Modify is ... begin -- Modify for I in 1 .. 200 loop The_Value := Object.Read; Object.Write (The_Value - 0.125); if The_Value < -1.0E7 then The_Value := 1.0; end if; end loop; end Modify; ... -- Block statement to be timed declare Contending_Tasks : array (1 .. 5) of Modify; begin null; -- 5 tasks contend for access to protected data end;

See ACES V2.0, test "a9_pt_prot_access_02"

Compare with Monitor Task: See ACES V2.0, test "tk_rz_entry_access_02"

Page 50: Ada 95 Protected Objects for Synchronizing Shared Data Structures

50

Ada 95 Quality & Style Guide 10.6.7 (Performance) Real-Time Systems Annex

Guidelines: For cases where both rendezvous and protected types are inefficient, consider the use of the Real-Time Systems Annex (Annex D).

Rationale: The packages Ada.Synchronous_Task_Control and Ada.Asynchronous_Task_Control have been defined to provide an alternative to tasking and protected types for use in applications where a minimal run-time is desired.

Page 51: Ada 95 Protected Objects for Synchronizing Shared Data Structures

51

ISO TR 15942 - Guide for the Use of the Ada Programming Language in High Integrity Systems 1

Guidelines : High integrity systems traditionally do not make use of high-level language features such as concurrency

Recommends Concurrency Model: - Fixed number of tasks - Tasks interact via use of shared data (i.e., no rendezvous) - Ravenscar Profile defined for high integrity, efficient systems Developed at 8th International Real-Time Ada Workshop in 1997

Page 52: Ada 95 Protected Objects for Synchronizing Shared Data Structures

52

ISO TR 15942 - Guide for the Use of the Ada Programming Language in High Integrity Systems 2

Ravenscar Profile (portions pertaining to Protected Objects only):

b. No unchecked deallocation of protected objects c. No dynamic allocation of protected objects e. Library level protected objects with no entries (to ensure atomic updates to shared data) f. Library level protected objects with a single entry (for invocation signalling). This entry has a barrier consisting of a single Boolean variable, moreover only a single task may queue this entry h. Atomic and Volatile pragmas j. Count attribute for protected entries (but not within entry barriers) m. Protected procedures as interrupt handlers

13 items in profile - 7 are related to Protected Objects

Page 53: Ada 95 Protected Objects for Synchronizing Shared Data Structures

53

Automated Tools to Analyze Protected Objects

ASIS Bases Tools (e.g., Ada Analyzer, AdaSTAT) Non-Locals in Guards Protected Operations With Blocking Operations Usage (e.g., Who uses each Protected Object) Verify Ravenscar profile is satisfied (AdaSTAT)

ASIS Can Query Each Protected Operations Syntactic Element

Page 54: Ada 95 Protected Objects for Synchronizing Shared Data Structures

54

Conclusion

Ada 95 Protected Objects provide a safe mechanism to synchronize data and the control of resources (devices)

Implemented with Mutual Exclusion for protected subprograms

Implemented with Guarded Queues for protected entries Protected Objects need to be lean and mean (should be of

short duration) Highly efficient compared to Ada 83 implementations Much generic design guidance in Ada Q&S Guide Many design considerations for building complex system ASIS Tools provide capabilities to analyze Protected Objects

Discussion???Other Issues???