Ada 95 Quality and Style Guide Chapter 6

Chapter 6: Concurrency - TOC - 6.2 COMMUNICATION

6.2.5 Selective Accepts and Entry Calls

guideline

  • Use caution with conditional entry calls to task entries.
  • Use caution with selective accept with else parts.
  • Do not depend upon a particular delay in timed entry calls to task entries.
  • Do not depend upon a particular delay in selective accepts with delay alternatives.
  • Consider using protected objects instead of the rendezvous for data-oriented synchronization.

  • example

    The conditional entry call in the following code results in a potential race condition that might degenerate into a busy waiting loop (i.e., perform the same calculation over and over). The task Current_Position containing entry Request_New_Coordinates might never execute if the loop-containing task (shown in the following code fragment) has a higher priority than Current_Position because it does not release the processing resource:

    task body Calculate_Flightpath is
    begin
       ...
       loop
      
          select
             Current_Position.Request_New_Coordinates (X, Y);
             -- calculate projected location based on new coordinates
             ...
      
          else
             -- calculate projected location based on last locations
             ...
          end select;
      
       end loop;
       ...
    end Calculate_Flightpath;
    

    The addition of a delay, as shown, may allow Current_Position to execute until it reaches an accept for Request_New_Coordinates:

    task body Calculate_Flightpath is
    begin
       ...
       loop
      
          select
             Current_Position.Request_New_Coordinates(X, Y);
             -- calculate projected location based on new coordinates
             ...
      
          else
             -- calculate projected location based on last locations
             ...
      
             delay until Time_To_Execute;
             Time_To_Execute := Time_To_Execute + Period;
          end select;
      
       end loop;
       ...
    end Calculate_Flightpath;
    
    

    The following selective accept with else again does not degenerate into a busy wait loop only because of the addition of a delay statement:

    task body Buffer_Messages is
    
       ...
    
    begin
    
       ...
    
       loop
          delay until Time_To_Execute;
    
          select
             accept Get_New_Message (Message : in     String) do
                -- copy message to parameters
                ...
             end Get_New_Message;
          else  -- Don't wait for rendezvous
             -- perform built in test Functions
             ...
          end select;
    
          Time_To_Execute := Time_To_Execute + Period;
       end loop;
    
       ...
    
    end Buffer_Messages;
    
    

    The following timed entry call might be considered an unacceptable implementation if lost communications with the reactor for over 25 milliseconds results in a critical situation:

    task body Monitor_Reactor is
       ...
    begin
       ...
       loop
      
          select
             Reactor.Status(OK);
      
          or
             delay 0.025;
             -- lost communication for more that 25 milliseconds
             Emergency_Shutdown;
          end select;
      
          -- process reactor status
          ...
       end loop;
       ...
    end Monitor_Reactor;
    
    

    In the following "selective accept with delay" example, the accuracy of the coordinate calculation function is bounded by time. For example, the required accuracy cannot be obtained unless Period is within + or - 0.005 seconds. This period cannot be guaranteed because of the inaccuracy of the delay statement:

    task body Current_Position is
    begin
       ...
       loop
      
          select
             accept Request_New_Coordinates (X :    out Integer;
                                             Y :    out Integer) do
                -- copy coordinates to parameters
                ...
             end Request_New_Coordinates;
      
          or
             delay until Time_To_Execute;
          end select;
      
          Time_To_Execute := Time_To_Execute + Period;
          -- Read Sensors
          -- execute coordinate transformations
       end loop;
       ...
    end Current_Position;
    
    

    rationale

    Use of these constructs always poses a risk of race conditions. Using them in loops, particularly with poorly chosen task priorities , can have the effect of busy waiting.

    These constructs are very much implementation dependent. For conditional entry calls and selective accepts with else parts, the Ada Reference Manual (1995, §9.7) does not define "immediately." For timed entry calls and selective accepts with delay alternatives, implementors might have ideas of time that differ from each other and from your own. Like the delay statement, the delay alternative on the select construct might wait longer than the time required (see Guideline 6.1.7).

    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. See Guideline 6.1.1 for an example of this use of protected objects.


    < Previous Page Search Contents Index Next Page >
    1 2 3 4 5 6 7 8 9 10 11
    TOC TOC TOC TOC TOC TOC TOC TOC TOC TOC TOC
    Appendix References Bibliography