MonitoredQueueImpl.mesa
Copyright Ó 1985, 1986, 1991 by Xerox Corporation. All rights reserved.
written by Paxton. December 1981
last written by Paxton. August 10, 1982 1:27 pm
Last Edited by: Maxwell, January 5, 1983 12:34 pm
Doug Wyatt, March 3, 1985 5:00:34 pm PST
DIRECTORY
MonitoredQueue;
MonitoredQueueImpl: CEDAR MONITOR LOCKS queue USING queue: MQ
EXPORTS MonitoredQueue
= BEGIN
MQ: TYPE = REF QueueBody;
QueueBody: PUBLIC TYPE = MONITORED RECORD [
start, end, free: LIST OF REF ANY ¬ NIL,
closed: BOOL ¬ FALSE,
change: CONDITION
];
QueueClosed: PUBLIC ERROR = CODE;
EndOfQueue: PUBLIC ERROR = CODE;
Create: PUBLIC PROC RETURNS [queue: MQ] = {
RETURN[NEW[QueueBody ¬ []]];
};
Add: PUBLIC PROC [item: REF ANY, queue: MQ] = { AddIt[item, queue, FALSE] };
adds item to queue
causes ERROR QueueClosed if have already called Close[queue]
AddToSet: PUBLIC PROC [item: REF ANY, queue: MQ] = { AddIt[item, queue, TRUE] };
adds item to queue unless it is already in it
causes ERROR QueueClosed if queue is closed
AddIt: ENTRY PROC [item: REF ANY, queue: MQ, toSet: BOOL] = { OPEN queue;
ENABLE UNWIND => NULL;
new: LIST OF REF ANY;
IF closed THEN ERROR QueueClosed;
IF toSet THEN -- check if item is alreay in queue
FOR list: LIST OF REF ANY ¬ start, list.rest UNTIL list=NIL DO
IF list.first = item THEN RETURN; -- already in queue
ENDLOOP;
IF free # NIL THEN { new ¬ free; free ¬ free.rest; new.rest ¬ NIL; new.first ¬ item }
ELSE new ¬ LIST[item];
IF end=NIL THEN start ¬ new
ELSE end.rest ¬ new;
end ¬ new;
NOTIFY change;
};
Remove: PUBLIC ENTRY PROC [queue: MQ] RETURNS [item: REF ANY] = { OPEN queue;
returns next item
causes ERROR EndOfQueue if have called Close[queue] and no more items
ENABLE UNWIND => NULL;
current: LIST OF REF ANY;
UNTIL closed OR start # NIL DO WAIT change; ENDLOOP;
IF (current ¬ start) = NIL THEN ERROR EndOfQueue;
item ¬ current.first; current.first ¬ NIL;
start ¬ current.rest; current.rest ¬ free; free ¬ current;
IF start = NIL THEN {
end ¬ NIL; -- have removed last entry
IF closed THEN BROADCAST change --for possible Reset-- }};
Close: PUBLIC ENTRY PROC [queue: MQ] = { OPEN queue;
ENABLE UNWIND => NULL;
closed ¬ TRUE;
BROADCAST change -- may be several waiting Remove's -- };
Reset: PUBLIC ENTRY PROC [queue: MQ] = { OPEN queue;
this waits until queue is closed and empty, then reopens it
ENABLE UNWIND => NULL;
UNTIL closed AND start = NIL DO WAIT change; ENDLOOP;
closed ¬ FALSE };
END.