-- FIFOImpl.mesa
-- last edited: July 13, 1981 8:27 AM

DIRECTORY
FIFO,
FIFOConnectorBool,
FIFOConnectorCard,
FIFOGuardian,
FIFOScheduler,
WF;

FIFOImpl: MONITOR
IMPORTS Init: FIFOConnectorBool, ReadReq: FIFOConnectorBool, WriteReq: FIFOConnectorBool, SpaceAv: FIFOConnectorBool, DataAv: FIFOConnectorBool, DataIn: FIFOConnectorCard, DataOut: FIFOConnectorCard, FIFOGuardian, FIFOScheduler, WF
EXPORTS FIFO = {

-- Public

-- Control logic
Main: PUBLIC PROC = {
p, q, r, s: PROCESS;
WF.WF0["Process Main started.*n"];
-- s ← FORK FIFOGuardian.Main[];
DataIn.DataflowRequest[ComputeDataflow];
rp ← wp ← 0;
ComputeDataflow[];
DO
SetQuit[FALSE];
Init.GetNew[FALSE];
InitRp[];
InitWp[];

p ← FIFOScheduler.Fork[InitProc];
q ← FIFOScheduler.Fork[ReadProc];
r ← FIFOScheduler.Fork[WriteProc];
FIFOScheduler.NotifyQueue[];
[] ← JOIN p;
[] ← JOIN q;
[] ← JOIN r;
FIFOScheduler.IncCurrent[];
ENDLOOP;
FIFOScheduler.ProcessEnd[];
};

-- Private

UnstableDataflow: SIGNAL = CODE;

Quit: BOOLEAN;

A: ARRAY [0..length) OF CARDINAL;
length: CARDINAL = 1001;
rp, wp: CARDINAL;

-- Data flow procs.
ComputeDataflow: ENTRY PROC = {
Dataflow[]};

Dataflow: INTERNAL PROC = {
state: RECORD [
DataAv, SpaceAv: BOOLEAN,
AwpIndex, Awp, DataOut: CARDINAL];
THROUGH [1..100] DO
DataAv.Stuff[state.DataAv ←
(NOT ReadReq.Grab[]) AND (rp<wp)];
SpaceAv.Stuff[state.SpaceAv ←
(NOT WriteReq.Grab[]) AND (wp<rp+3)];
A[state.AwpIndex ← wp] ← state.Awp ← DataIn.Grab[];
DataOut.Stuff[state.DataOut ← A[rp]];
IF (state.DataAv # ((NOT ReadReq.Grab[]) AND (rp<wp))) OR
(state.SpaceAv # ((NOT WriteReq.Grab[])
AND (wp<rp+3))) OR
(state.AwpIndex # wp) OR
(state.Awp # DataIn.Grab[]) OR
(state.DataOut # A[rp]) THEN LOOP
ELSE RETURN;
REPEAT
FINISHED => SIGNAL UnstableDataflow;
ENDLOOP;
};

-- Processes
InitProc: PROC = {
WF.WF0["InitProc started.*n"];
WF.WF1["Init halt: %u*n", FIFOScheduler.GetProcessSize[]];
Init.GetNew[TRUE];
WF.WF1["Init restart: %u*n", FIFOScheduler.GetProcessSize[]];
SetQuit[TRUE];
WF.WF0["InitProc terminated.*n"];
FIFOScheduler.ProcessEnd[];
};
ReadProc: PROC = {
WF.WF0[" ReadProc started.*n"];
DO
ReadReq.GetNew[FALSE];
IncRp[];
IF QuitHi[] THEN EXIT
ENDLOOP;
WF.WF0[" ReadProc terminated: %u.*n"];
FIFOScheduler.ProcessEnd[];};
WriteProc: PROC = {
WF.WF0[" WriteProc started.*n"];
DO
WriteReq.GetNew[FALSE];
IncWp[];
IF QuitHi[] THEN EXIT
ENDLOOP;
WF.WF0[" WriteProc terminated.*n"];
FIFOScheduler.ProcessEnd[];};

InitRp: ENTRY PROC = {
rp ← 0;
Dataflow[]};
InitWp: ENTRY PROC = {
wp ← 0;
Dataflow[]};
IncRp: ENTRY PROC = {
rp ← rp + 1;
Dataflow[]};
IncWp: ENTRY PROC = {
wp ← wp + 1;
Dataflow[]};
SetQuit: ENTRY PROC [v: BOOLEAN] = {
Quit ← v};
QuitHi: ENTRY PROC RETURNS [BOOLEAN] = {
RETURN[Quit]};

}.