/** Concurrency: State Models and Java Programs
 *             Jeff Magee and Jeff Kramer
 *  
 */

/* Supervisor Worker - with correct termination
*/

const False = 0
const True  = 1
range Bool = False..True

const N          = 2                  //Maximum Number of tuple copies
set   Tuples     = {task,result,task.stop}
set   TupleAlpha = {{in,out,rd,rdp[Bool],inp[Bool]}.Tuples}

TUPLE(T='any) = TUPLE[0],
TUPLE[i:0..N] 
  = (out[T]                   -> TUPLE[i+1]
    |when (i>0) in[T]         -> TUPLE[i-1]
    |when (i>0) inp[True][T]  -> TUPLE[i-1]
    |when (i==0)inp[False][T] -> TUPLE[i]
    |when (i>0) rd[T]         -> TUPLE[i]
    |rdp[i>0][T]              -> TUPLE[i]
    ).

||TUPLESPACE = forall [t:Tuples] TUPLE(t).

SUPERVISOR   = TASK[1],
TASK[i:1..N] = 
  (out.task  -> 
     if i<N then TASK[i+1] else RESULT[1]),
RESULT[i:1..N] = 
  (in.result -> 
     if i<N then RESULT[i+1] else FINISH),
FINISH = 
  (out.task.stop -> end -> STOP)
  + TupleAlpha.

WORKER = 
  (in.task -> out.result -> WORKER
  |in.task.stop -> out.task.stop-> end -> STOP
  ) + TupleAlpha.

ATEND = (end  ->ENDED),
ENDED = (ended->ENDED).

||SUPERVISOR_WORKER
    = (supervisor:SUPERVISOR 
      ||{redWork,blueWork}:WORKER
      ||{supervisor,redWork,blueWork}::TUPLESPACE
      ||ATEND
      )/{end/{supervisor,redWork,blueWork}.end}.

progress END = {ended}

menu TEST = {redWork,blueWork}.in.task
