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: BOOLEANFALSE;
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: BOOLEANFALSE;
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.