Very confused by Ada tasking, can not explain the execution outcome.
- From: climber.cui@xxxxxxxxx
- Date: Fri, 29 Aug 2008 18:54:53 -0700 (PDT)
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;
.
- Follow-Ups:
- Re: Very confused by Ada tasking, can not explain the execution outcome.
- From: Jeffrey R. Carter
- Re: Very confused by Ada tasking, can not explain the execution outcome.
- Prev by Date: Re: and then... (a curiosity)
- Next by Date: Re: Very confused by Ada tasking, can not explain the execution outcome.
- Previous by thread: and then... (a curiosity)
- Next by thread: Re: Very confused by Ada tasking, can not explain the execution outcome.
- Index(es):
Relevant Pages
|