-- TiogaPGMonitorImpl.Mesa -- last written by Paxton. February 8, 1981 5:47 PM DIRECTORY TiogaFiles: FROM "TiogaFiles" USING [controlBlock, textBlock], TiogaPGStreams; TiogaPGMonitorImpl: MONITOR LOCKS pgm USING pgm: PGM EXPORTS TiogaPGStreams = BEGIN OPEN filesI: TiogaFiles, TiogaPGStreams; PGM: TYPE = REF PGMBody; PGMBody: PUBLIC TYPE = MONITORED RECORD [ text, control, writes, deferred: MList ]; MList: TYPE = REF MListBody; MListBody: TYPE = RECORD [ first, last: BlockList, done: BOOLEAN ← FALSE, available: CONDITION ]; BlockList: TYPE = REF BlockListBody; BlockListBody: TYPE = RECORD [ next: BlockList, block: Block ]; CreatePGM: PUBLIC PROC [mode: PGStreamMode] RETURNS [pgm: PGM] = BEGIN pgm ← NEW[PGMBody]; SELECT mode FROM read => { pgm.text ← NEW[MListBody]; pgm.control ← NEW[MListBody] }; write => { pgm.writes ← NEW[MListBody]; pgm.deferred ← NEW[MListBody] }; ENDCASE => ERROR; END; AddToMList: INTERNAL PROC [mlst: MList, block: Block] = BEGIN itm: BlockList ← NEW[BlockListBody ← [NIL, block]]; IF mlst.first # NIL THEN mlst.last.next ← itm ELSE mlst.first ← itm; mlst.last ← itm; NOTIFY mlst.available; END; GetFromMList: INTERNAL PROC [mlst: MList, pgm: PGM] RETURNS [block: Block] = BEGIN itm: BlockList; WHILE (itm ← mlst.first) = NIL AND ~mlst.done DO WAIT mlst.available; ENDLOOP; IF itm=NIL THEN RETURN [NIL]; -- done block ← itm.block; IF itm = mlst.last THEN mlst.first ← mlst.last ← NIL ELSE mlst.first ← mlst.first.next; END; AddToControlList: PUBLIC ENTRY PROC [pgm: PGM, block: Block] = { ENABLE UNWIND => NULL; AddToMList[pgm.control, block] }; GetFromControlList: PUBLIC ENTRY PROC [pgm: PGM] RETURNS [Block] = { ENABLE UNWIND => NULL; RETURN [GetFromMList[pgm.control, pgm]] }; SetDone: INTERNAL PROC [mlst: MList] = INLINE { mlst.done ← TRUE; NOTIFY mlst.available }; ControlReadsDone: PUBLIC ENTRY PROC [pgm: PGM] = { ENABLE UNWIND => NULL; SetDone[pgm.control] }; TextReadsDone: PUBLIC ENTRY PROC [pgm: PGM] = { ENABLE UNWIND => NULL; SetDone[pgm.text] }; WriteTextBlock: PUBLIC ENTRY PROC [pgm: PGM, block: Block] = { ENABLE UNWIND => NULL; AddToMList[pgm.writes, block] }; WriteControlBlock: PUBLIC ENTRY PROC [pgm: PGM, block: Block] = { ENABLE UNWIND => NULL; AddToMList[pgm.deferred, block] }; GetFromWriteList: PUBLIC ENTRY PROC [pgm: PGM] RETURNS [Block] = { ENABLE UNWIND => NULL; RETURN[GetFromMList[pgm.writes, pgm]] }; WritesDone: PUBLIC ENTRY PROC [pgm: PGM] = { ENABLE UNWIND => NULL; writes, deferred: MList; deferred ← pgm.deferred; IF deferred.first # NIL THEN -- move to writes IF (writes ← pgm.writes).first # NIL THEN BEGIN writes.last.next ← deferred.first; writes.last ← deferred.last; deferred.first ← deferred.last ← NIL; END ELSE BEGIN writes.first ← deferred.first; writes.last ← deferred.last; deferred.first ← deferred.last ← NIL; END; SetDone[pgm.writes] }; END.