-- RTQueueImpl.Mesa FOR USE BY THE COLLECTOR
-- last edited June 16, 1983 9:15 pm by Paul Rovner
DIRECTORY RTQueue;
RTQueueImpl: MONITOR -- protects q's
LOCKS LOOPHOLE[q, RealQ] USING q: Q
EXPORTS RTQueue
= BEGIN
OPEN RTQueue;
RealQ: TYPE = REF QRec;
QRec: TYPE = MONITORED RECORD
[ nRefs: CARDINAL,
nextIndex: CARDINAL ← 0,
nonEmpty: CONDITION,
refs: SEQUENCE count: CARDINAL OF REF ANY];
-- Exported procedures (public)
New: PUBLIC PROC[nRefs: CARDINAL ← 10] RETURNS[Q] =
{RETURN[[NEW[QRec[nRefs] ← [nRefs: nRefs, LOCK:, nonEmpty:, refs: NULL]]]]};
-- called only by the collector
Enqueue: PUBLIC ENTRY PROC[ref: REF ANY, q: Q] RETURNS[full: BOOLEAN]=
{ ENABLE UNWIND => NULL;
rq: RealQ = LOOPHOLE[q];
IF rq.nRefs = rq.nextIndex THEN RETURN[TRUE];
-- THE BELOW IS NOT A REFERENCE COUNTED ASSIGNMENT
LOOPHOLE[rq.refs[rq.nextIndex], LONG POINTER] ← LOOPHOLE[ref, LONG POINTER];
rq.nextIndex ← rq.nextIndex + 1;
NOTIFY rq.nonEmpty;
RETURN[FALSE]};
dummy: REF ANY ← NIL;
Dequeue: PUBLIC PROC[q: Q] RETURNS[ref: REF ANY] = {
ref ← DoDequeue[q];
-- now decrement ref's reference count
LOOPHOLE[dummy, LONG POINTER] ← LOOPHOLE[ref, LONG POINTER];
dummy ← NIL;
};
DoDequeue: ENTRY PROC[q: Q] RETURNS[ref: REF ANY] =
{ ENABLE UNWIND => NULL;
rq: RealQ = LOOPHOLE[q];
WHILE QEmpty[rq] DO WAIT rq.nonEmpty; ENDLOOP;
rq.nextIndex ← rq.nextIndex - 1;
ref ← rq.refs[rq.nextIndex];
-- THE BELOW IS NOT A REFERENCE COUNTED ASSIGNMENT
LOOPHOLE[rq.refs[rq.nextIndex], LONG POINTER] ← NIL};
Empty: PUBLIC ENTRY PROC[q: Q] RETURNS[BOOLEAN] =
{ RETURN[QEmpty[LOOPHOLE[q]]]};
QEmpty: INTERNAL PROC[rq: RealQ] RETURNS[BOOLEAN] =
INLINE {RETURN[rq.nextIndex = 0]};
END.