PDInterpControlImpl.mesa
Michael Plass, November 11, 1983 2:14 pm
DIRECTORY PDInterpBasic, PDInterpControl, PDFileFormat, PDInterpInput, PDInterpPage, PDInterpReader, Process;
PDInterpControlImpl:
MONITOR
IMPORTS PDInterpInput, PDInterpPage, PDInterpReader, Process
EXPORTS PDInterpControl
~
BEGIN OPEN PDInterpControl;
queueMaxSize: NAT ~ 10;
QueueEntry:
TYPE ~
RECORD [
inputHandle: PDInterpInput.Handle,
pageSpec: PageSpec
];
queueSize: NAT ← 0;
queue: ARRAY [0..queueMaxSize) OF QueueEntry;
queueChange: CONDITION;
JobDone:
ENTRY
PROC ~ {
FOR i:
NAT
IN [1..queueSize)
DO
queue[i-1] ← queue[i];
ENDLOOP;
queueSize ← queueSize - 1;
BROADCAST queueChange;
};
ReQueue:
ENTRY
PROC ~ {
queueEntry: QueueEntry ← queue[0];
FOR i:
NAT
IN [1..queueSize)
DO
queue[i-1] ← queue[i];
ENDLOOP;
queue[queueSize-1] ← queueEntry;
BROADCAST queueChange;
};
UnQueue:
ENTRY
PROC [handle: PDInterpInput.Handle] ~ {
found: BOOLEAN ← FALSE;
FOR i:
NAT
IN [1..queueSize)
DO
IF found THEN queue[i-1] ← queue[i]
ELSE found ← queue[i].inputHandle = handle;
ENDLOOP;
IF found THEN {queueSize ← queueSize - 1; BROADCAST queueChange};
};
RequestService:
PUBLIC
ENTRY PROC [handle: PDInterpInput.Handle, pageSpec: PageSpec] ~ {
UNTIL queueSize < queueMaxSize DO WAIT queueChange ENDLOOP;
queue[queueSize] ← [handle, pageSpec];
queueSize ← queueSize + 1;
BROADCAST queueChange;
};
PrintOne:
PROC [reader: PDInterpReader.Handle] ~ {
finished: BOOLEAN ← FALSE;
FOR i:
NAT
IN [0..maxRanges)
UNTIL finished
DO
pageRange: PageRange ← queue[0].pageSpec[i];
skip: NAT ← pageRange.skipCount;
UNTIL finished
OR skip = 0
DO
WITH PDInterpReader.Get[reader]
SELECT
FROM
stateChange: PDInterpReader.CommandBuffer.stateChange => {
SELECT stateChange.whatChanged
FROM
imageStart => finished ← PDInterpInput.ReportStatus[reader.input, startImage, queueSize, 0, reader.page, reader.pass, reader.index].abort;
documentEnd => finished ← TRUE;
imageEnd => skip ← skip - 1;
ENDCASE => NULL;
};
ENDCASE => NULL;
ENDLOOP;
UNTIL finished
OR pageRange.printCount = 0
DO
IF PDInterpPage.InterpretPage[reader].ok
THEN {
finished ← PDInterpInput.ReportStatus[reader.input, startImage, queueSize, 0, reader.page, reader.pass, reader.index].abort;
pageRange.printCount ← pageRange.printCount - 1;
pageRange.skipCount ← pageRange.skipCount + 1;
}
ELSE finished ← TRUE;
ENDLOOP;
queue[0].pageSpec[i] ← pageRange;
ENDLOOP;
[] ← PDInterpInput.ReportStatus[reader.input, transmissionComplete, queueSize, 0, reader.page, reader.pass, reader.index];
};
WaitForOne:
ENTRY
PROC ~ {
UNTIL queueSize > 0 DO WAIT queueChange ENDLOOP;
};
PrintProcess:
PROC ~ {
reader: PDInterpReader.Handle ← NIL;
ReportStatus:
PROC [status: PDInterpBasic.Status]
RETURNS [abort:
BOOLEAN] ~ {
IF reader =
NIL
THEN {
abort ← PDInterpInput.ReportStatus[
handle: queue[0].inputHandle,
status: status,
queueSize: queueSize,
queuePosition: 0,
page: 0,
pass: 0,
sourceIndex: 0
]
}
ELSE {
abort ← PDInterpInput.ReportStatus[
handle: queue[0].inputHandle,
status: status,
queueSize: queueSize,
queuePosition: 0,
page: reader.page,
pass: reader.pass,
sourceIndex: reader.index
]
};
};
DO
ENABLE PDInterpReader.Warning => {
IF ReportStatus[code].abort
THEN
CONTINUE
ELSE
RESUME};
WaitForOne[];
reader ← PDInterpReader.Open[queue[0].inputHandle
! PDInterpReader.Error => {[]←ReportStatus[code]; CONTINUE}
];
IF reader #
NIL
THEN {
PrintOne[reader ! PDInterpReader.Error => {[] ← ReportStatus[code]; CONTINUE}];
reader ← PDInterpReader.Close[reader];
};
JobDone[];
ENDLOOP;
};
QueueWatch:
PROC = {
snapshot: ARRAY [0..queueMaxSize) OF PDInterpInput.Handle;
count: NAT;
SnapshotQueue:
ENTRY
PROC ~ {
WAIT queueChange;
count ← queueSize;
FOR i:
NAT
IN [0..count)
DO
snapshot[i] ← queue[i].inputHandle;
ENDLOOP;
};
DO
SnapshotQueue[];
FOR i:
NAT
IN [1..count)
DO
IF PDInterpInput.ReportStatus[snapshot[i], queued, queueSize, i, 0, 0, 0].abort THEN UnQueue[snapshot[i]];
ENDLOOP;
ENDLOOP;
};
Process.Detach[FORK QueueWatch[]];
Process.Detach[FORK PrintProcess[]];
END.