PROCESSOR MODULE dining_philosophers;
IMPLEMENTATION
CONST num_phils =  5;    (* number philosophers *)
      num_iter  =  3;    (* number of eat-think cycles *)


MONITOR table;
VAR fork       : ARRAY[0..num_phils-1] OF BOOLEAN;
    return_fork: ARRAY[0..num_phils-1] OF CONDITION;
    i          : INTEGER;

ENTRY get_forks (pos: INTEGER);
VAR i,pos1: INTEGER;
BEGIN
  pos1 := (pos+1) MOD num_phils;
  WHILE NOT (fork[pos] AND fork[pos1]) DO
    WAIT(return_fork[pos])
  END;
  fork[pos ] := FALSE;
  fork[pos1] := FALSE;
  (* *) WriteString("get forks: ");
  (* *) FOR i:=0 TO num_phils-1 DO WriteBool(fork[i]); Write(' '); END;
  (* *) WriteLn;
  (* *) WriteString("philosopher"); WriteInt(pos,3);
  (* *) WriteString(" eating"); WriteLn;
END get_forks;

ENTRY put_forks (pos: INTEGER);
VAR i,pos1,posm1: INTEGER;
BEGIN
  pos1  := (pos+1) MOD num_phils;
  posm1 := (pos-1) MOD num_phils;
  fork[pos ] := TRUE;
  fork[pos1] := TRUE;
  SIGNAL(return_fork[pos1]);
  SIGNAL(return_fork[posm1]);
  (* *) WriteString("put forks: ");
  (* *) FOR i:=0 TO num_phils-1 DO WriteBool(fork[i]); Write(' '); END;
  (* *) WriteLn;
  (* *) WriteString("philosopher"); WriteInt(pos,3);
  (* *) WriteString(" thinking"); WriteLn;
END put_forks;

BEGIN (* monitor-init *)
  FOR i:=0 TO num_phils-1 DO 
    fork[i] := TRUE 
  END;
END MONITOR table;


PROCESS philosopher;
VAR i,num: INTEGER;
BEGIN
  num := PROCESSNO-1;
  FOR i:=1 TO num_iter DO
    table:get_forks(num);
    (* eating *)
    table:put_forks(num);
    (* thinking *)
  END
END PROCESS philosopher;


BEGIN
 START(philosopher,num_phils)
END PROCESSOR MODULE dining_philosophers.

