DIRECTORY
	FIFO,
	FIFOGuardian,
	Process,
	RandomCard,
	WF;

FIFODriver: MONITOR
	IMPORTS FIFO, FIFOGuardian, Process, RandomCard, WF = {

p,q,r,s: PROCESS;
i: CARDINAL;

ReadSchedule, WriteSchedule: CONDITION;
Scheduler: PROC = {
	DO
		IF RandomCard.Choose[0,1] = 0 THEN NotifyRead[]
		ELSE NotifyWrite[];
		Process.Yield[]
	ENDLOOP};
NotifyRead: ENTRY PROC = {
	NOTIFY ReadSchedule};
NotifyWrite: ENTRY PROC = {
	NOTIFY WriteSchedule};
WaitReadSched: ENTRY PROC = {
	WAIT ReadSchedule};
WaitWriteSched: ENTRY PROC = {
	WAIT WriteSchedule};
Reader: PROC = {
	WF.WF0["  Reader started.*n"];
	THROUGH [0..50) DO
		WaitReadSched[];
		UNTIL FIFO.DataAvHi[] DO WaitReadSched[] ENDLOOP;
		FIFOGuardian.SetReadRequest[TRUE];
		WF.WF1["%u  ", FIFO.GetDataOut[]];
		WaitReadSched[];
		FIFOGuardian.SetReadRequest[FALSE];
	ENDLOOP;
	WF.WF0["  Reader terminated.*n"];
	};
Writer: PROC = {
	WF.WF0[" Writer started.*n"];
	FOR i IN [0..50) DO
		WaitWriteSched[];
		UNTIL FIFO.SpaceAvHi[] DO WaitWriteSched[] ENDLOOP;
		FIFOGuardian.SetDataIn[i];
		FIFOGuardian.SetWriteRequest[TRUE];
		WF.WF1["%u-  ", i];
		WaitWriteSched[];
		FIFOGuardian.SetWriteRequest[FALSE];
	ENDLOOP;
	WF.WF0[" Writer terminated.*n"];
	};

[] ← RandomCard.InitRandom[-1];
START FIFO.FIFOImpl;
r ← FORK FIFO.Main[];
FIFO.SetInit[FALSE];
s ← FORK Scheduler[];
p ← FORK Reader[];
q ← FORK Writer[];

[] ← JOIN p;
[] ← JOIN q;
}.