-- FIFOImpl.sak -- last edited by Suzuki: 20-Nov-81 16:02:15 DIRECTORY Connector: TYPE, FIFO: TYPE, Process: TYPE, Scheduler: TYPE; FIFOImpl: MONITOR IMPORTS Connector, Process, Scheduler EXPORTS FIFO = BEGIN choice1: Connector.Choice ← Connector.CreateChoice[]; FIFOFunc: PUBLIC PROC [size: CARDINAL, Init, WriteRequest, ReadRequest: Connector.Handle, DIn: Connector.Handle, SpaceAv, DataAv: Connector.Handle, DOut: Connector.Handle] = { guardian: PROC = {{Initialized: BOOLEAN ← FALSE; DO SELECT Connector.GetChoice[choice1] FROM 1 => {IF NARROW[Connector.Get[ReadRequest], REF BOOLEAN]↑ OR NARROW[Connector.Get[WriteRequest], REF BOOLEAN]↑ THEN ERROR; Initialized ← TRUE}; 2 => IF NOT Initialized OR NARROW[Connector.Get[Init], REF BOOLEAN]↑ OR NOT NARROW[Connector.Get[DataAv], REF BOOLEAN]↑ THEN ERROR; 3 => IF NOT Initialized OR NARROW[Connector.Get[Init], REF BOOLEAN]↑ OR NOT NARROW[Connector.Get[SpaceAv], REF BOOLEAN]↑ THEN ERROR ENDCASE => ERROR ENDLOOP}}; p: PROCESS; Scheduler.IncCurrent[]; Process.Yield[]; p ← Scheduler.Fork[guardian]; Connector.RegisterUp[choice1, 1, Init]; Connector.RegisterUp[choice1, 2, ReadRequest]; Connector.RegisterUp[choice1, 3, WriteRequest]; {A: ARRAY INTEGER [1..37] OF CARDINAL; rp, wp: CARDINAL; DO Connector.GetNew[Init, TRUE]; rp ← wp ← 0; A[rp] ← NARROW[Connector.Get[DIn], REF CARDINAL]↑; Connector.Put[DOut, NEW[CARDINAL ← A[wp]]]; Connector.Put[SpaceAv, NEW[BOOLEAN ← FALSE]]; Connector.Put[DataAv, NEW[BOOLEAN ← FALSE]]; {d1: PROC = {Connector.GetNew[Init, TRUE]; NULL; Process.Abort[p2]}; d2: PROC = { {ENABLE {ABORTED => GO TO End}; {st1: PROC = {DO Connector.GetNew[ReadRequest, TRUE]; {Connector.Put[DataAv, NEW[BOOLEAN ← FALSE]]; rp ← rp + 1; A[rp] ← NARROW[Connector.Get[DIn], REF CARDINAL]↑; Connector.Put[DOut, NEW[CARDINAL ← A[wp]]]; Connector.Put[SpaceAv, NEW [BOOLEAN ← NOT NARROW[Connector.Get[WriteRequest], REF BOOLEAN]↑ AND wp < rp + size]]}; Connector.GetNew[ReadRequest, FALSE]; Connector.Put[DataAv, NEW[BOOLEAN ← rp < wp]] ENDLOOP}; process1: PROCESS; process1 ← Scheduler.Fork[st1]; DO Connector.GetNew[WriteRequest, TRUE]; {Connector.Put[SpaceAv, NEW[BOOLEAN ← FALSE]]; wp ← wp + 1; Connector.Put[DOut, NEW[CARDINAL ← A[wp]]]; Connector.Put[DataAv, NEW [BOOLEAN ← NOT NARROW[Connector.Get[ReadRequest], REF BOOLEAN]↑ AND rp < wp]]}; Connector.GetNew[WriteRequest, FALSE]; Connector.Put[SpaceAv, NEW[BOOLEAN ← wp < rp + size]] ENDLOOP; [] ← Scheduler.Join[process1]} EXITS End => NULL}}; p1, p2: PROCESS; p1 ← Scheduler.Fork[d1]; p2 ← Scheduler.Fork[d2]; [] ← Scheduler.Join[p1]; [] ← Scheduler.Join[p2]} ENDLOOP}; [] ← Scheduler.Join[p]}; NULL; END.