comp.lang.ada
 help / color / mirror / Atom feed
From: "jimmaureenrogers@worldnet.att.net" <jimmaureenrogers@worldnet.att.net>
Subject: Re: Very confused by Ada tasking, can not explain the execution outcome.
Date: Fri, 29 Aug 2008 21:17:26 -0700 (PDT)
Date: 2008-08-29T21:17:26-07:00	[thread overview]
Message-ID: <023de8e6-ce28-4a97-8103-ff855289a795@b30g2000prf.googlegroups.com> (raw)
In-Reply-To: a5408e90-8113-4a35-bc1f-81f2613d6616@73g2000hsx.googlegroups.com

On Aug 29, 7:54 pm, climber....@gmail.com wrote:
> Hi all,
>   I am trying to simulate a concurrent resource allocator with Ada's
> task and protected type.
>   The idea is simple: there are several resource available (total
> number is N=8), shared by user_thread. Each user first randomly
> generate 4 numbers ranged between 0 and 7, which would represent the
> resource needed to access. The resources therefore are implemented by
> semaphores, which in turn implemented by protected objects.
>   The user_thread is not going to interact with each other by making
> entry calls, so no entry is defined in tasks. The task representing
> the user_thread simply select a procedure defined in the task body non-
> deterministically, until the counter, 'rounds' reached its limit.  I
> am now only testing a single task for execution. However, the outcome
> is very confusing:
>   - the last sentence of the task body, which is a put_line statement
> is never executed, but the task terminates.
>  - also, the per task counter 'rounds', was never incremented, it
> stays the same as the initial value. The only procedure increment
> 'rounds' is procedure 'use_res', but the procedure was never called
> during the execution.  If you notice the entry condition for the while
> loop, 'while rounds<2 loop', how could it get out of the loop if
> 'rounds' was never incremented??  why the program still terminates??
>   I am stuck on this issue. Although i am not new to programming, I do
> not know Ada very well. Could someone help me out here?

The program runs fine with a few modifications to your conditions.
Note that I changed the index to a modular type. This eliminates any
need to check for out of bounds indexing due to your arithmetic.
Modular arithmetic wraps to values within the type definition.

Your program contains two unused variables: Rd and Index. You should
clean up the unused clutter.

Your original version never incremented Rounds because the conditions
for Use_Res were never satisfied.

with Ada.Text_Io;
with Ada.Numerics.Discrete_Random;
use  Ada.Text_Io;

procedure Multi_Res_Alloc_A is

   N  : constant := 8; -- number of resources to share

   type Res_Index is mod N;

   type Bool_Array is array (Res_Index) of Boolean;

   subtype N_Res is Integer range 0..99;
   package Random_Int is new Ada.Numerics.Discrete_Random (N_Res);
   use Random_Int;
   G : Generator;

   -- -------------------------------------
   protected type Semaphore is
      entry P;
      entry V;
   private
      Value : Boolean := True;
   end Semaphore;
   -- -------------------------------------
   protected body Semaphore is
      entry P when Value is
      begin
         Value:= False;
      end P;

      entry V when not Value is
      begin
         Value:= True;
      end V;
   end Semaphore;
   -- -------------------------------------
   R : array (Res_Index) of Semaphore;

   -- -------------------------------------
   task type User_Thread ;

   task body User_Thread is

      Rounds : Integer    := 0;
      Next,
      I      : Integer;
      State  : Integer    := - 1;
      D      : Res_Index    := 0;
      Needs  : Bool_Array := (Others => False);

      X : Integer := 0;
      C : Integer := 0;

      procedure Acquire_No_Wait is
      begin
         D:=D+1;
      end Acquire_No_Wait;

      procedure Acquire_Wait is
      begin
         R(D).P;
         D:=D+1;
      end Acquire_Wait;

      procedure Use_Res is
      begin
         State:=1;
         Put_Line("******* Eating now *******");
         while D>0 loop
            D:=D-1;
            if Needs(D) then
               R(D).V;
            end if;
         end loop;
         State:=-1;
         Rounds:=Rounds+1;
      end Use_Res;

      procedure Want_Res is
      begin
         C:=0;
         State:=0;
         Reset(G);  -- start the generator in a unique state in each
run
         while C<4 loop
            --random x
            X := Random(G);
            Needs(Res_Index(X mod N)):= True;
            C:=C+1;
         end loop;
      end Want_Res;

   begin

      Put_Line("-->> Enter task body..");
      Reset(G);  -- reset the random number generator
      while Rounds<2 loop
         Next := Random(G) mod 4;   -- number of actions per task = 4
         Put_Line("  >> next =" & Integer'Image(Next) & ";  state =" &
Integer'Image(State));

         if Next=0 and State=0 and not Needs(D) then
            Put_Line("------> acquiring resource,no waiting <------");
            Acquire_No_Wait;
         end if;

         if Next=1 and State=0 and Needs(D) then
            Put_Line("------> acquire and waiting resource <------");
            Acquire_Wait;
         end if;

         if Next=2 and State=0 then
            Put_Line("------> USING resource <------");
            Use_Res;
         end if;

         if Next=3 and State=-1 then
            Put_Line("------> Want resource(s) <------");
            Want_Res;
         end if;

         --Put_Line(">> ****** rounds = " & INTEGER'Image(rounds) &
"*******" );
         Next:= (Next+1) mod 4;
         I:=0;
         Put_Line("    >>> next =" & Integer'Image(Next) & ";  state
=" & Integer'Image(State));
         while (I<3) and (Rounds<2) loop

            if Next=0 and State=0 and not Needs(D) then
               Put_Line("  >> acquiring resource,no waiting <------");
               Acquire_No_Wait;
            end if;

            if Next=1 and State=0 and Needs(D)  then
               Put_Line("  >> acquire and waiting resource <------");
               Acquire_Wait;
            end if;

            if Next=2 and State=0 then
               Put_Line("  >> USING resource <------");
               Use_Res;
            end if;

            if Next=3 and State=-1 then
               Put_Line("  >> Want resource(s) <------");
               Want_Res;
            end if;

            --Put_Line(">> ****** rounds = " & INTEGER'Image(rounds) &
"*******" );
            Next:= (Next+1) mod 4;
            Put_Line("   >>>> next =" & Integer'Image(Next) & ";
state =" & Integer'Image(State));
            I:=I+1;
         end loop;
         Put_Line("..... rounds =" & Integer'Image(Rounds) & "...." );
      end loop;

      Put_Line("TASK EXITS ::  rounds =" & Integer'Image(Rounds) &
"...." );

   end User_Thread;
   -- -------------------------------------

   U1 : User_Thread;

begin
   null;
end Multi_Res_Alloc_A;

Jim Rogers



  reply	other threads:[~2008-08-30  4:17 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-08-30  1:54 Very confused by Ada tasking, can not explain the execution outcome climber.cui
2008-08-30  4:17 ` jimmaureenrogers [this message]
2008-08-30  9:34   ` climber.cui
2008-08-30 10:59     ` Damien Carbonne
2008-08-31 13:37       ` Stephen Leake
2008-08-30  5:12 ` Jeffrey R. Carter
2008-08-30  9:42   ` climber.cui
2008-08-30 13:40     ` Georg Bauhaus
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox