简体   繁体   中英

Ada tasks and termination

I've been reading a little bit about tasks in ada at http://en.wikibooks.org/wiki/Ada_Programming/Tasking and thought that i'll write a little thing with tasks myself. Since i've read a small course on Pintos recently i thought i'd implement a little readers-writers algorithm. This is my attempt at it:

procedure Test_Queue is

   type Int_Array is array(1..10) of Integer;

   task type Queue is
      entry Quit;
      entry Pop(Elem : out Integer);
      entry Push(Elem : in Integer);
   end Queue;

   task body Queue is
      Elems_In_Queue : Integer := 0;
      Q : Int_Array;
   begin
      loop
         select
            accept Push(Elem : in Integer) do
               Put_Line("Push");
               Elems_In_Queue := Elems_In_Queue + 1;
               Q(Elems_In_Queue) := Elem;
            end Push;
         or
            when Elems_In_Queue > 0 =>
               accept Pop(Elem : out Integer) do
                    Put_Line("Pop");
                Elem := Q(Elems_In_Queue);
                Elems_In_Queue := Elems_In_Queue - 1;
               end Pop;
         else
            delay 1.0;
            Put_Line("Waited");
            accept Quit;
            exit;
         end select;
      end loop;
      Put_Line("Got out of the loop");
   end Queue;

   Q : Queue;
   X : Integer;

begin
   Put_Line("Started");
   Q.Push(10);
   Put_Line("Pushed");
   Q.Push(11);
   Put_Line("Pushed");
   Q.Pop(X);
   Put_Line("Integer:" & Integer'Image(X));
   Q.Quit;
   Put_Line("Done");
end Test_Queue;

Might be worth mentioning that the behaviour i would like to see is that when no operations (push/pop) have been made to the queue/stack for 1 second i would like the task to terminate/exit the infinite loop.

But this just outputs "Started" and then goes to my delay 1.0 and outputs "Wait". This is not exactly what I expected since i have accept for at least push and that is the first thing i call. Where have i been thinking wrong and why doesn't this work? Also, are there any more sources with some examples as for how to do tasking in Ada? I managed to implement this by creating a Semaphore and Lock in 2 different tasks but that seemed to be a bad solution and not very adaesque.

Having improved the diagnostics, it is clear that on startup, neither of the Select alternatives was immediately available so the Queue task was going straight to the Else part, and after 1 second delay, waiting to accept Quit .

Meanwhile the main task was blocking on its first (unconditional, untimed!) Push entry call, so that it could never issue the Quit entry call. Result : Deadlock.

The solution (described in Burns & Welling on p.108) is simply to change ELSE to OR so that the third (Delay) option is still a Select alternative. Then in each iteration, the earliest of (Push, Pop or Delay) will be accepted.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM