-- 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.