comp.lang.ada
 help / color / mirror / Atom feed
From: climber.cui@gmail.com
Subject: Re: Very confused by Ada tasking, can not explain the execution outcome.
Date: Sat, 30 Aug 2008 02:34:33 -0700 (PDT)
Date: 2008-08-30T02:34:33-07:00	[thread overview]
Message-ID: <898a5f1d-75f7-4f66-a241-440e9c225454@z66g2000hsc.googlegroups.com> (raw)
In-Reply-To: 023de8e6-ce28-4a97-8103-ff855289a795@b30g2000prf.googlegroups.com

On Aug 30, 12:17 am, "jimmaureenrog...@worldnet.att.net"
<jimmaureenrog...@worldnet.att.net> wrote:
> 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

Thank you Jim for modifying the program and making it work. I saw how
you modify the guarding conditions for the procedures. In fact, the
conditions are fine by themselves, because i wrote the same program in
Java. However, the modified program is working now. It indeed reminds
me that Ada probably follows the 'strict evaluation' rule when it
comes to the boolean expressions, so in
  if Next=1 and State=0 and D<N and Needs(D)  then ...
  Ada probably would evaluate all the predicates connect by logical
AND, but as soon as D=N is reached, array index for Needs(_) would go
out of bound (because Needs is defined to be  array(0..N-1) of
boolean). I am just guessing here.

This would not cause exceptions in Java, because java follows the non-
strict evaluation rule.

tony



  reply	other threads:[~2008-08-30  9:34 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
2008-08-30  9:34   ` climber.cui [this message]
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