SharedQueue.mesa
Copyright (C) Xerox Corporation 1986. All rights reserved.
last edited by Prochaska 14-May-86 13:35:35
Tim Diebert: October 2, 1986 1:51:52 pm PDT
Ruseli Binsol: November 19, 1986 11:46:46 am PST
DIRECTORY
Process USING [DisableAborts, EnableAborts, DisableTimeout, SetTimeout, Milliseconds, MsecToTicks];
SharedQueue: DEFINITIONS LOCKS queue USING queue: Handle IMPORTS Process = BEGIN
SharedQueue provides an interface for multiple clients to access the same queue without losing data. Each client must keep track of its own head (reading) index; the module keeps track of the current tail (writing) index.
Constants:
length: CARDINAL = 12;
maximumLapse: Process.Milliseconds = LAST[Process.Milliseconds];
TYPEs:
Handle: TYPE = LONG POINTER TO Object;
Item: TYPE = WORD;
Object: TYPE = MONITORED RECORD [
body: ARRAY [FIRST[CARDINAL]..length) OF Item,
tail: CARDINALFIRST[WORD],
nonEmpty: CONDITION];
timeout: Item = LAST[WORD];
value used for timeout return, cannot be valid normal Item
INLINE ENTRY PROCEDUREs:
GetCurrentHead: PROCEDURE [queue: Handle, head: REF CARDINAL] =
INLINE BEGIN ENABLE UNWIND => NULL; IF head # NIL THEN head^ ← queue.tail; END;
Empty: ENTRY PROCEDURE [queue: Handle, head: REF CARDINAL]
RETURNS [empty: BOOLEAN] = INLINE
BEGIN ENABLE UNWIND => NULL; RETURN[empty: queue.tail = head^]; END;
Full: ENTRY PROCEDURE [queue: Handle, head: REF CARDINAL] RETURNS [full: BOOLEAN] = INLINE BEGIN
ENABLE UNWIND => NULL;
RETURN[full: (queue.tail + 1) MOD length = head^];
END;
Initialize: ENTRY PROCEDURE [queue: Handle, enableAbort, enableTimeout: BOOLEANTRUE,
lapse: Process.Milliseconds ← maximumLapse] = TRUSTED INLINE BEGIN
ENABLE UNWIND => NULL;
IF enableAbort
THEN Process.EnableAborts[pCondition: @queue.nonEmpty]
ELSE Process.DisableAborts[pCondition: @queue.nonEmpty];
IF enableTimeout
THEN Process.SetTimeout[condition: @queue.nonEmpty, ticks: Process.MsecToTicks[lapse]]
ELSE Process.DisableTimeout[condition: @queue.nonEmpty];
RETURN;
END;
Note parm head is pointer to head index, which Pop[] updates as a side effect
Pop: ENTRY PROCEDURE [queue: Handle, head: REF CARDINAL] RETURNS [item: Item] = INLINE BEGIN
ENABLE UNWIND => NULL;
IF queue.tail = head^ THEN WAIT queue.nonEmpty;
IF queue.tail = head^
THEN item ← timeout
ELSE BEGIN item ← queue.body[head^]; head^ ← SUCC[head^] MOD length; END;
END;
Push: ENTRY PROCEDURE [queue: Handle, item: Item] = INLINE BEGIN
ENABLE UNWIND => NULL;
queue.body[queue.tail] ← item;
queue.tail ← SUCC[queue.tail] MOD length;
BROADCAST queue.nonEmpty;
RETURN;
END;
END.
LOG
14-May-86 13:35:35 -- Prochaska -- Created module.