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