6.5 The requeue Statement

[ Table of Contents ] Prev ] Chapter Overview ] Next ] [ Glossary/Index ]

A requeue statement can appear as the last executable statement of an entry body (or of an accept statement of a task body). The effect of a requeue statement is to remove a task that is executing in an entry and place it on a different queue -- different from the queue corresponding to the entry body (or accept statement) now executing. It is common (but not always true) for the new queue to correspond to another entry of the same object -- sometimes an "internal" entry declared in the private part of a protected object (or type) declaration.

A requeue statement may have one of the following forms:

When requeing to another entry of the same object
requeue Entry_Name;
When requeing to an entry of a different object
requeue Object_Name.Entry_Name;
Abortable requeue
requeue Entry_Name with abort;

The third form, abortable requeue, is included for completeness. We will not attempt to explain or illustrate it in this introductory volume.

Example Program with requeue Statements

The following example is adapted from an example in Section 18.3.1 of [Cohen96]. We have added the test procedure, with its several tasks, in order to provide a runnable illustration.

The Load_Control package exports a protected object, Load_Manager, which exports a protected procedure and one "external" protected entry. It also has a private part, which declares an "internal" protected entry. Both entry bodies have a requeue statement.

The test procedure declares a Load_Monitor task and two task types, as shown, and then declares an array of Urgent_Task tasks and an array of Casual_Task tasks.

Im6-6.gif (5486 bytes)

To understand the following example it is important to understand that the barrier conditions on the entry bodies ("when not Retrying" and "when Retrying") are re-evaluated each time the "state" of the protected object changes. In this case, there are state changes each time the protected procedure, Set_Load, is called by the Load_Monitor task.

Source Code Listing

--------------------------------------------------------------
--------  Load_Control  --------------------------------------
--  This package provides a protected object that controls 
--  the servicing of calling tasks, such that they are kept 
--  waiting until the system Load is less than some threshold 
--  value (different for each task type). 
--------------------------------------------------------------
package Load_Control is
  subtype Load_Type is Integer range 0..5;
    
  protected Load_Manager is
    entry Wait_Until_Load_Less_Than(Threshold : in Load_Type);
    procedure Set_Load(Load : in Load_Type);
  private
    Current_Load : Load_Type := 5;
    Retrying     : Boolean := False;
    entry Wait_To_Retry(Load : in Load_Type);
  end Load_Manager;
end Load_Control;
--------------------------------------------------------------  
package body Load_Control is
    
  protected body Load_Manager is  
    ----------------------------------
    entry Wait_Until_Load_Less_Than(Threshold : in Load_Type)
      when not Retrying is
    begin
      if Current_Load > Threshold then
        requeue Wait_To_Retry;                -- requeue statement
      end if;
    end Wait_Until_Load_Less_Than;
    ----------------------------------
    procedure Set_Load(Load : in Load_Type) is
    begin
      Current_Load := Load;
      Retrying := True;    
    end Set_Load;
    ----------------------------------
    entry Wait_To_Retry(Load : in Load_Type) 
      when Retrying is
    begin
      if Wait_To_Retry'Count = 0 then         -- Count attribute
        Retrying := False;  
      end if;
      requeue Wait_Until_Load_Less_Than;      -- requeue statement
    end Wait_To_Retry;
    ----------------------------------
  end Load_Manager;
end Load_Control;
--------------------------------------------------------------
--------  Test_Requeue  --------------------------------------
--  This procedure creates a task that reduces the Load to 3 
--  and then to 1, and two arrays of tasks of type Urgent_Task 
--  and Casual_Task having threshold values of 4 and 2, 
--  respectively
--------------------------------------------------------------
with Ada.Text_IO; use Ada.Text_IO;
with Load_Control;
procedure Test_Requeue is
  --------------------------------------------
  task Load_Monitor;
  task body Load_Monitor is
  begin
    delay 4.0;
    Load_Control.Load_Manager.Set_Load(3);
    delay 2.0;
    Load_Control.Load_Manager.Set_Load(1);    
  end Load_Monitor;
  --------------------------------------------
  task type Urgent_Task;
  task body Urgent_Task is                    -- Threshold = 4
  begin
    delay 2.0;
    Put_Line("Urgent_Task will get on queue");
    Load_Control.Load_Manager.Wait_Until_Load_Less_Than(4);
    Put_Line("Urgent task completed");    
  end Urgent_Task;
  --------------------------------------------
  task type Casual_Task;
  task body Casual_Task is                    -- Threshold = 2
  begin
    Put_Line("Casual task will get on queue");
    Load_Control.Load_Manager.Wait_Until_Load_Less_Than(2);
    Put_Line("Casual task completed");    
  end Casual_Task;
  --------------------------------------------
  UT : array(1..2) of Urgent_Task;            -- declare 2 tasks
  CT : array(1..2) of Casual_Task;            -- declare 2 tasks
  --------------------------------------------  
begin
  null;
end Test_Requeue;
--------------------------------------------------------------

The above program produces the following output:

     Casual task will get on queue
     Casual task will get on queue
     Urgent task will get on queue
     Urgent task will get on queue 
     Urgent task completed
     Urgent task completed
     Casual task completed
     Casual task completed

Note that the casual tasks get on line first, because of the 2.0 second delay built into the urgent tasks. All four tasks are initially requeued onto the Wait_To_Retry queue. After 4 seconds the Load is reduced and the urgent tasks are requeued back onto the Wait_Until_Load_Less_Than queue, and then completed. After 6 seconds the Load is reduced again and the casual tasks are requeued and completed.

Related Topics

A.2  Simple and Compound Statements

[ Back to top of pagePrev ] Next ]