Very confused by Ada tasking, can not explain the execution outcome.



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?

Thanks a lot.
The entire program (runnable) would be attached at the end of the
message.

tony

--------------------------------------------------------
--------------------------------------------------
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
RD:constant := 2; -- number of rounds

type BOOL_ARRAY is array(0..N-1) 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: INTEGER := 1;
end Semaphore;
-- -------------------------------------
protected body Semaphore is
entry P when value>0 is
begin
value:= value-1;
end P;

entry V when value=0 is
begin
value:= value+1;
end V;
end Semaphore;
-- -------------------------------------
r: array(0..N-1) of Semaphore;

-- -------------------------------------
task type User_thread ;

task body User_thread is

rounds: INTEGER :=0 ;
next, i, index : INTEGER;
state: INTEGER :=-1 ;
d : INTEGER :=0;
needs: BOOL_ARRAY := (0..N-1 => 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(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 d<N and not needs(d) then
Put_Line("------> acquiring resource,no waiting <------");
acquire_no_wait;
end if;

if next=1 and state=0 and d<N and needs(d) then
Put_Line("------> acquire and waiting resource <------");
acquire_wait;
end if;

if next=2 and state=0 and d>N-1 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 d<N and not needs(d) then
Put_Line(" >> acquiring resource,no waiting <------");
acquire_no_wait;
end if;

if next=1 and state=0 and d<N and needs(d) then
Put_Line(" >> acquire and waiting resource <------");
acquire_wait;
end if;

if next=2 and state=0 and d>N-1 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;
.



Relevant Pages

  • Re: Very confused by Ada tasking, can not explain the execution outcome.
    ... I am trying to simulate a concurrent resource allocator with Ada's ... task and protected type. ... entry calls, so no entry is defined in tasks. ... loop, 'while rounds<2 loop', how could it get out of the loop if ...
    (comp.lang.ada)
  • Re: task-safe hash table?
    ... protected type p_type is ... entry awhen p_dummy = 0 is ... 1_000 loop ...
    (comp.lang.ada)
  • Re: [Pcihpd-discuss] Re: ACPI problem with PCI Express Native Hot-plug driver
    ... system has two hot-pluggable PCI Express slots). ... PCI bus 0x0 Resource structure 0. ... Resource Type: Bus Number Range ... pciehp_save_config: In do loop ...
    (Linux-Kernel)
  • RE: Creating a que
    ... and entry count in a collection. ... if eo.Count> 0 then bMoreData = True ... At the beginning of the loop you assume this is the last time through the ... Then you go through each item in the Entries ...
    (microsoft.public.excel.programming)
  • RE: Creating a que
    ... and entry count in a collection. ... if eo.Count> 0 then bMoreData = True ... At the beginning of the loop you assume this is the last time through the ... Then you go through each item in the Entries ...
    (microsoft.public.excel.programming)