<> <> <> <> DIRECTORY RefQueue; RefQueueImpl: MONITOR -- protects q's LOCKS queue USING queue: Queue EXPORTS RefQueue = BEGIN Queue: TYPE = REF Object; Object: PUBLIC TYPE = MONITORED RECORD [ nEntries: NAT, nextIndex: NAT _ 0, nonEmpty: CONDITION, refs: SEQUENCE count: NAT OF REF ANY ]; New: PUBLIC PROC[nEntries: NAT] RETURNS[new: Queue] = { new _ NEW[Object[nEntries] _ [nEntries: nEntries, LOCK:, nonEmpty:, refs: NULL]]; }; Enqueue: PUBLIC ENTRY PROC[queue: Queue, ref: REF ANY] RETURNS[full: BOOL _ FALSE] = { ENABLE UNWIND => NULL; IF QFull[queue] THEN RETURN[TRUE]; queue.refs[queue.nextIndex] _ ref; queue.nextIndex _ queue.nextIndex + 1; NOTIFY queue.nonEmpty; }; Dequeue: PUBLIC ENTRY PROC[queue: Queue] RETURNS[ref: REF ANY] = { ENABLE UNWIND => NULL; WHILE QEmpty[queue] DO WAIT queue.nonEmpty ENDLOOP; queue.nextIndex _ queue.nextIndex - 1; ref _ queue.refs[queue.nextIndex]; queue.refs[queue.nextIndex] _ NIL; }; IsFull: PUBLIC ENTRY PROC[queue: Queue] RETURNS[BOOL] = { ENABLE UNWIND => NULL; RETURN[QFull[queue]]; }; QFull: INTERNAL PROC[queue: Queue] RETURNS[BOOL] = INLINE { RETURN[queue.nextIndex = queue.nEntries]}; IsEmpty: PUBLIC ENTRY PROC[queue: Queue] RETURNS[BOOL] = { ENABLE UNWIND => NULL; RETURN[QEmpty[queue]]; }; QEmpty: INTERNAL PROC[queue: Queue] RETURNS[BOOL] = INLINE { RETURN[queue.nextIndex = 0]}; END.