1 / 54

Ada 95 Protected Objects for Synchronizing Shared Data Structures

Ada 95 Protected Objects for Synchronizing Shared Data Structures. Currie Colket The MITRE Corporation Phone: (703) 883-7381 Email: colket@mitre.org | colket@acm.org DC SIGAda 14 March 2002. SIGAda Home Page  http://www.acm.org/sigada.

milt
Download Presentation

Ada 95 Protected Objects for Synchronizing Shared Data Structures

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

  2. So What Are Protected Objects?

  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

  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; Consider: type Position is record Latitude: Float; Longitude: Float; end record; • And the effects of • Time Slicing • Expiration of a delay of a higher priority task

  5. Motivation For Protected Object - 2 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; With Mutual Exclusion 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; Still: type Position is record Latitude: Float; Longitude: Float; end record;

  6. IntroductionProtected Objects • Protected 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 Declaration Required a Protected Body

  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.

  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.

  9. IntroductionSimple Example of Protected Objects protectedCounteris procedureIncrement (New_Value: out Positive); functionGet_Counterreturn Integer; private Data: Integer := 0; endCounter; protected bodyCounteris procedure Increment (New_Value: out Positive) is begin Data := Data + 1; New_Value := Data; endIncrement; functionGet_Counter is begin return Data; endGet_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;

  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

  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.3.1 Ada LRM 3.10 Ada LRM 3.11

  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

  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

  14. Ada 95 RM Example of Declaration of Protected Type protected bodyResourceis entrySeizewhen not Busy is begin Busy := True; endSeize; procedureReleaseis begin Busy := False; endRelease; endResource; protected typeResourceis entrySeize; procedureRelease; private Busy : Boolean := False; endResource; Examples of protected objects: Control : Resource; Flags : array (1 .. 4) ofResource;

  15. Ada 95 RM Example of Single Protected Declaration protected 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; Note: Index, Item, & Item_Array are global types protected bodyShared_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; Not allowed to declare new objects Examples: Shared_Array.Set_Component(N, E); E := Shared_Array. Get_Component(M);

  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.

  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)

  18. Ada 95 RM 9.5 Intertask Communications - 2 Model: Entries always have barrier conditions Eggshell 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” Tasks waiting on barrier (in entry queues) Guard  Task executing (at most one) Get_Item  Set_Item Tasks outside (in unstructured way)

  19. Ada 95 RM 9.5 Intertask Communications - 3 Renamings allowed

  20. Function Call Procedure Call Blocked/ Not-Blocked Resource 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 For functions Blocked If procedure accessing For procedures Blocked If functions accessing Not really called blocked

  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 raised else Bounded error might result in deadlock or a (nested) protected action on the same target object.

  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.

  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 are only allowed for task declarations and protected declarations. Note barrier is required Entry_declarations, with the corresponding entry_bodies are used to define potentially queued operations on protected objects. Condition for entry_barrier can be any private or global data except for the object of the parameter_profile - Index & Discriminant OK

  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.

  25. Queue Queue Queue Queue Guard not Busy Guard not Busy Guard not Busy Guard not Busy Resource 1 Resource 2 Resource 3 Resource 4 Ada 95 RM 9.5.3 Entry Calls - 1 entry_call_statement ::= entry_name [actual_parameter_part]; protected bodyResource is entry Seize when not Busy is begin Busy := True; end Seize; procedure Release is begin Busy := False; end Release; end Resource; For: Device : array(1 .. 4) of Resource; Device(3).Seize;

  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 the • entry queues (in case some entry barrier depends on a Count attribute).

  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.

  28. Ada 95 RM 9.5.4 Requeue Statement - 2 • Notes (continued): • If the requeue_statement includes the reserved words with abort (it is a • requeue-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 protected • against cancellation while queued as the result of the requeue_statement.

  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.

  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.

  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;

  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.

  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)

  34. Design Considerations Example 1: System Example System Protected Objects System Devices (Resources) System Data (e.g., Own_Position) Distributed Environment (How many processors?) Subsystem Protected Objects Multiple Subsystem Tasks How critical is timing of data System Control Shared Here? ... Navigation Sensor Control Tracking Fire Control ... Radar Infra Red ESM Acoustics How is Data Here?

  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.

  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.

  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.

  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;

  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;

  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.

  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?

  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?

  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).

  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.

  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 protection Rationale: • 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.

  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.

  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.

  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.

  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"

  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.

More Related