-- from john -- I modified WorkLock to be a task, and not a protected type -- list unmodeled -- inlined package RW is ---------------------------------------------------------------------- type ZERO_POS is (zero, positive); task ResultLock is entry signal; entry wait; end ResultLock; ---------------------------------------------------------------------- task ASActivePool is entry ASinit; entry StartUp; entry ShutDown; entry Get(done : out Boolean); entry Put; --newWork : in out WorkList); entry Finished; entry Execute; entry Complete; end ASActivePool; ---------------------------------------------------------------------- task AS1ActiveWorker is entry StartUp; entry ShutDown; entry Execute; end AS1ActiveWorker; task AS2ActiveWorker is entry StartUp; entry ShutDown; entry Execute; end AS2ActiveWorker; task AS3ActiveWorker is entry StartUp; entry ShutDown; entry Execute; end AS3ActiveWorker; task main; ---------------------------------------------------------------------- end RW; package body RW is task body ResultLock is value : Boolean := TRUE; begin loop select when not value => accept signal; value := TRUE; or when value => accept wait; value := FALSE; end select; end loop; end ResultLock; task body ASActivePool is executeDone : Boolean := TRUE; waitPhaseWorkers, idleWorkers : Natural range 0 ..3; -- workCount : Natural; workCount : ZERO_POS; choice: Boolean; -- added by me begin accept ASinit; accept StartUp; workCount := zero; Outer: loop loop select accept ShutDown; exit Outer; or accept Finished; accept Shutdown; exit Outer; or accept Put do -- nondeterministic choice if choice then workCount := positive; end if; end Put; or accept Execute; AS1ActiveWorker.Execute; AS2ActiveWorker.Execute; AS3ActiveWorker.Execute; exit; end select; end loop; executeDone := FALSE; idleWorkers := 3; waitPhaseWorkers := 0; loop select when (workCount = positive) or executeDone => accept Get(done : out Boolean) do if executeDone then done := TRUE; waitPhaseWorkers := waitPhaseWorkers + 1; else done := FALSE; -- nondeterministic choice if choice then workCount := positive; else workCount := zero; end if; idleWorkers := idleWorkers - 1; end if; end Get; or accept Put do -- nondeterministic choice if choice then workCount := positive; end if; end Put; idleWorkers := idleWorkers + 1; or accept Finished; executeDone := TRUE; waitPhaseWorkers := waitPhaseWorkers + 1; end select; if idleWorkers = 3 and workCount=zero then executeDone := TRUE; end if; exit when waitPhaseWorkers = 3; end loop; accept Complete; end loop Outer; end ASActivePool; ---------------------------------------------------------------------- task body AS1ActiveWorker is done : Boolean; choice_m : natural range 1 .. 6; begin accept StartUp; loop select accept ShutDown; exit; or accept Execute; end select; -- Repeatedly get work, process it, put new work loop -- Attempt to get new work ASActivePool.Get(done); exit when done; -- Perform the work -- call dowork loop -- nondeterministic choice case choice_m is when 1 => -- Create; ASActivePool.StartUp; AS1ActiveWorker.Startup; AS2ActiveWorker.Startup; AS3ActiveWorker.Startup; when 2 => -- Input; ASActivePool.Put; when 3 => -- Execute; ASActivePool.Execute; ASActivePool.Complete; when 4 => -- Destroy; ASActivePool.Finished; AS1ActiveWorker.ShutDown; AS2ActiveWorker.ShutDown; AS3ActiveWorker.ShutDown; ASActivePool.ShutDown; when 5 => null; when 6 => exit; end case; end loop; -- nondeterministic choice for done -- Short-circuit the computation if indicated if done then ASActivePool.Finished; exit; end if; -- Process the results ResultLock.wait; -- call doresult loop -- nondeterministic choice case choice_m is when 1 => -- Create; ASActivePool.StartUp; AS1ActiveWorker.Startup; AS2ActiveWorker.Startup; AS3ActiveWorker.Startup; when 2 => -- Input; ASActivePool.Put; when 3 => -- Execute; ASActivePool.Execute; ASActivePool.Complete; when 4 => -- Destroy; ASActivePool.Finished; AS1ActiveWorker.ShutDown; AS2ActiveWorker.ShutDown; AS3ActiveWorker.ShutDown; ASActivePool.ShutDown; when 5 => null; when 6 => exit; end case; end loop; -- nondet choice for done ResultLock.signal; -- Short-circuit the computation if indicated if done then ASActivePool.Finished; exit; end if; -- Put the new work back ASActivePool.Put; end loop; end loop; end AS1ActiveWorker; ---------------------------------------------------------------------- task body AS2ActiveWorker is done : Boolean; choice_m : natural range 1 .. 6; begin accept StartUp; loop select accept ShutDown; exit; or accept Execute; end select; -- Repeatedly get work, process it, put new work loop -- Attempt to get new work ASActivePool.Get(done); exit when done; -- Perform the work loop -- nondeterministic choice case choice_m is when 1 => -- Create; ASActivePool.StartUp; AS1ActiveWorker.Startup; AS2ActiveWorker.Startup; AS3ActiveWorker.Startup; when 2 => -- Input; ASActivePool.Put; when 3 => -- Execute; ASActivePool.Execute; ASActivePool.Complete; when 4 => -- Destroy; ASActivePool.Finished; AS1ActiveWorker.ShutDown; AS2ActiveWorker.ShutDown; AS3ActiveWorker.ShutDown; ASActivePool.ShutDown; when 5 => null; when 6 => exit; end case; end loop; -- Short-circuit the computation if indicated if done then ASActivePool.Finished; exit; end if; -- Process the results ResultLock.wait; loop -- nondeterministic choice case choice_m is when 1 => -- Create; ASActivePool.StartUp; AS1ActiveWorker.Startup; AS2ActiveWorker.Startup; AS3ActiveWorker.Startup; when 2 => -- Input; ASActivePool.Put; when 3 => -- Execute; ASActivePool.Execute; ASActivePool.Complete; when 4 => -- Destroy; ASActivePool.Finished; AS1ActiveWorker.ShutDown; AS2ActiveWorker.ShutDown; AS3ActiveWorker.ShutDown; ASActivePool.ShutDown; when 5 => null; when 6 => exit; end case; end loop; ResultLock.signal; if done then ASActivePool.Finished; exit; end if; -- Put the new work back ASActivePool.Put; end loop; end loop; end AS2ActiveWorker; ---------------------------------------------------------------------- task body AS3ActiveWorker is done : Boolean; choice_m : natural range 1 .. 6; begin accept StartUp; loop select accept ShutDown; exit; or accept Execute; end select; -- Repeatedly get work, process it, put new work loop -- Attempt to get new work ASActivePool.Get(done); exit when done; -- Perform the work loop -- nondeterministic choice case choice_m is when 1 => -- Create; ASActivePool.StartUp; AS1ActiveWorker.Startup; AS2ActiveWorker.Startup; AS3ActiveWorker.Startup; when 2 => -- Input; ASActivePool.Put; when 3 => -- Execute; ASActivePool.Execute; ASActivePool.Complete; when 4 => -- Destroy; ASActivePool.Finished; AS1ActiveWorker.ShutDown; AS2ActiveWorker.ShutDown; AS3ActiveWorker.ShutDown; ASActivePool.ShutDown; when 5 => null; when 6 => exit; end case; end loop; if done then ASActivePool.Finished; exit; end if; -- Process the results ResultLock.wait; loop -- nondeterministic choice case choice_m is when 1 => -- Create; ASActivePool.StartUp; AS1ActiveWorker.Startup; AS2ActiveWorker.Startup; AS3ActiveWorker.Startup; when 2 => -- Input; ASActivePool.Put; when 3 => -- Execute; ASActivePool.Execute; ASActivePool.Complete; when 4 => -- Destroy; ASActivePool.Finished; AS1ActiveWorker.ShutDown; AS2ActiveWorker.ShutDown; AS3ActiveWorker.ShutDown; ASActivePool.ShutDown; when 5 => null; when 6 => exit; end case; end loop; ResultLock.signal; -- Short-circuit the computation if indicated if done then ASActivePool.Finished; exit; end if; -- Put the new work back ASActivePool.Put; end loop; end loop; end AS3ActiveWorker; ---------------------------------------------------------------------- -- we add here the stub task body main is choice_m : natural range 1 .. 6; begin loop -- nondeterministic choice case choice_m is when 1 => -- Create; ASActivePool.StartUp; AS1ActiveWorker.Startup; AS2ActiveWorker.Startup; AS3ActiveWorker.Startup; when 2 => -- Input; ASActivePool.Put; when 3 => -- Execute; ASActivePool.Execute; ASActivePool.Complete; when 4 => -- Destroy; ASActivePool.Finished; AS1ActiveWorker.ShutDown; AS2ActiveWorker.ShutDown; AS3ActiveWorker.ShutDown; ASActivePool.ShutDown; when 5 => null; when 6 => exit; end case; end loop; end main; end RW;