<> <> <> <> DIRECTORY BasicTime USING [earliestGMT, GMT, Now, Period, Update], Queue USING [ElemProc], Rope USING [ROPE]; QueueImpl: CEDAR PROGRAM IMPORTS BasicTime EXPORTS Queue = BEGIN MQ: TYPE = REF MQRep; MQRep: PUBLIC TYPE = RECORD[ name: ROPE, elemList: LIST OF QElem _ NIL, lastSlot: LIST OF QElem _ NIL]; QElem: TYPE = REF QElemRep; QElemRep: PUBLIC TYPE = RECORD[ value: REF ANY, inhibitUntil: GMT _ notInhibited, inhibitReason: ROPE _ notInhibitedRope]; ROPE: TYPE = Rope.ROPE; GMT: TYPE = BasicTime.GMT; <> <<>> <> <<>> NewElem: PUBLIC PROC [value: REF ANY] RETURNS [newElem: QElem] = { RETURN[NEW[QElemRep _ [value]]]; }; Value: PUBLIC PROC [qElem: QElem] RETURNS [value: REF ANY] = { RETURN[qElem.value]; }; Create: PUBLIC PROC [name: ROPE] RETURNS [newQueue: MQ] = { newQueue _ NEW[MQRep _ [name: name]]; }; Name: PUBLIC PROC [queue: MQ] RETURNS [ROPE] = { RETURN[queue.name]; }; IsEmpty: PUBLIC PROC [queue: MQ] RETURNS [BOOL] = { RETURN[queue.elemList = NIL]; }; Enqueue: PUBLIC PROC [queue: MQ, qElem: QElem] = { <> ENABLE UNWIND => NULL; IF queue.lastSlot = NIL THEN -- empty queue queue.elemList _ queue.lastSlot _ LIST[qElem] ELSE { queue.lastSlot.rest _ LIST[qElem]; queue.lastSlot _ queue.lastSlot.rest; }; }; Dequeue: PUBLIC PROC [queue: MQ, value: REF ANY] = { <> ENABLE UNWIND => NULL; elemList: LIST OF QElem _ queue.elemList; previousList: LIST OF QElem; IF elemList = NIL THEN RETURN WITH ERROR NotOnQueue; IF elemList.first.value = value THEN { queue.elemList _ elemList.rest; IF queue.elemList = NIL THEN queue.lastSlot _ NIL; RETURN; }; previousList _ elemList; FOR restElems: LIST OF QElem _ elemList.rest, previousList.rest UNTIL restElems = NIL DO IF restElems.first.value = value THEN { previousList.rest _ restElems.rest; IF restElems.rest = NIL THEN queue.lastSlot _ previousList; RETURN; }; previousList _ restElems; ENDLOOP; ERROR NotOnQueue; }; NotOnQueue: PUBLIC ERROR = CODE; GetHead: PUBLIC PROC [queue: MQ] RETURNS [qElem: QElem] = { <> ENABLE UNWIND => NULL; elemList: LIST OF QElem = queue.elemList; IF elemList = NIL THEN RETURN [NIL]; RETURN[elemList.first]; }; GetProcessableElement: PUBLIC PROC [queue: MQ] RETURNS [qElem: QElem] = { ENABLE UNWIND => NULL; FOR restElems: LIST OF QElem _ queue.elemList, restElems.rest UNTIL restElems = NIL DO qElem: QElem = restElems.first; IF Inhibition[qElem].for = 0 THEN RETURN[qElem]; ENDLOOP; RETURN[NIL]; }; QueueEmpty: PUBLIC ERROR = CODE; Enumerate: PUBLIC PROC [queue: MQ, proc: Queue.ElemProc, procData: REF ANY _ NIL] = { FOR restElems: LIST OF QElem _ queue.elemList, restElems.rest UNTIL restElems = NIL DO qElem: QElem ~ restElems.first; IF NOT proc[qElem, procData] THEN EXIT; ENDLOOP; }; <> <> notInhibited: GMT ~ BasicTime.earliestGMT; notInhibitedRope: ROPE ~ "not inhibited"; Inhibit: PUBLIC PROC [qElem: QElem, for--seconds--: INT, why: ROPE] ~ { qElem.inhibitUntil _ BasicTime.Update[BasicTime.Now[], for]; qElem.inhibitReason _ why; }; Uninhibit: PUBLIC PROC [qElem: QElem, queue: MQ] ~ { qElem.inhibitUntil _ notInhibited; qElem.inhibitReason _ notInhibitedRope; }; Inhibition: PUBLIC PROC [qElem: QElem] RETURNS [for: INT, why: ROPE] = { for _ MAX[BasicTime.Period[from: BasicTime.Now[], to: qElem.inhibitUntil], 0]; IF for = 0 THEN qElem.inhibitReason _ notInhibitedRope; RETURN[for, qElem.inhibitReason]; }; END.