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