PDInterpControlImpl.mesa
Michael Plass, November 17, 1983 4:58 pm
DIRECTORY PDInterpBasic, PDInterpControl, PDTransferRpcControl, PDFileFormat, PDInterpPage, PDInterpReader, Process, MesaRPC, PDInterpControlRpcControl, Heap, PDTransfer;
PDInterpControlImpl:
MONITOR
IMPORTS MesaRPC, PDInterpPage, PDInterpReader, Process, PDTransferRpcControl, PDInterpControlRpcControl, Heap, PDTransfer
EXPORTS PDInterpControl
SHARES PDTransferRpcControl -- for creation of PDTransferRpcControl.InterfaceRecordObject
=
BEGIN OPEN PDInterpControl;
queueMaxSize: NAT = 10;
QueueEntry:
TYPE =
RECORD [
inputHandle: PDTransferRpcControl.InterfaceRecord,
pageSpec: PageSpec
];
queueSize: NAT ← 0;
queue: ARRAY [0..queueMaxSize) OF QueueEntry;
queueChange: CONDITION;
JobDone:
ENTRY
PROC = {
IF queue[0].inputHandle #
NIL
THEN {
Heap.systemZone.FREE[@(queue[0].inputHandle)];
};
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: PDTransferRpcControl.InterfaceRecord] = {
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};
};
ImportNewInterface:
PROC [interfaceName: MesaRPC.InterfaceName]
RETURNS [interface: PDTransferRpcControl.InterfaceRecord] = {
!!!!!!! This is a hack !!!!!!!
PDTransferRpcControl.ImportInterface[interfaceName];
interface ← Heap.systemZone.
NEW[PDTransferRpcControl.InterfaceRecordObject ← [
GetBlock: PDTransfer.GetBlock,
ReportStatus: PDTransfer.ReportStatus
]];
};
RequestService:
PUBLIC
ENTRY PROC [requestorName:
LONG
STRING, pageSpec: PageSpec] = {
interfaceName: MesaRPC.InterfaceName = [instance: requestorName];
handle: PDTransferRpcControl.InterfaceRecord = ImportNewInterface[interfaceName];
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 ← reader.input^.ReportStatus[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 ← reader.input.ReportStatus[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;
[] ← reader.input.ReportStatus[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 ← queue[0].inputHandle.ReportStatus[
status: status,
queueSize: queueSize,
queuePosition: 0,
page: 0,
pass: 0,
sourceIndex: 0
]
}
ELSE {
abort ← queue[0].inputHandle.ReportStatus[
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 PDTransferRpcControl.InterfaceRecord;
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 snapshot[i].ReportStatus[queued, queueSize, i, 0, 0, 0].abort THEN UnQueue[snapshot[i]];
ENDLOOP;
ENDLOOP;
};
Process.Detach[FORK QueueWatch[]];
Process.Detach[FORK PrintProcess[]];
PDInterpControlRpcControl.ExportInterface[
interfaceName: [instance: "Plass.pa"L],
user: "Plass.pa"L,
password: MesaRPC.MakeKey["IOTW3799"L]
];
END.