<> <> <> <> <> DIRECTORY Process USING [DisableAborts, EnableAborts, DisableTimeout, SetTimeout, Milliseconds, MsecToTicks]; SharedQueue: DEFINITIONS LOCKS queue USING queue: Handle IMPORTS Process = BEGIN <> <> length: CARDINAL = 12; maximumLapse: Process.Milliseconds = LAST[Process.Milliseconds]; <> Handle: TYPE = LONG POINTER TO Object; Item: TYPE = WORD; Object: TYPE = MONITORED RECORD [ body: ARRAY [FIRST[CARDINAL]..length) OF Item, tail: CARDINAL _ FIRST[WORD], nonEmpty: CONDITION]; timeout: Item = LAST[WORD]; <> <> 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: BOOLEAN _ TRUE, 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; <> 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.