GENERIC MODULEChannel (Elem, ElemQueue);
Channel implemented as a monitored queue
IMPORT Thread; IMPORT Debug; CONST DebugLevel = 100; REVEAL T = Public BRANDED OBJECT m: Thread.Mutex; nonempty: Thread.Condition; queue: ElemQueue.T; OVERRIDES init := Init; send := Send; recv := Recv; END; PROCEDUREInit (self: T): T = BEGIN self.m := NEW(Thread.Mutex); self.nonempty := NEW(Thread.Condition); self.queue := NEW(ElemQueue.T).init(); RETURN self; END Init; PROCEDURESend (self: T; elem: Elem.T) = BEGIN Debug.S("Channel sending",DebugLevel); LOCK self.m DO self.queue.put(elem); END; Thread.Signal(self.nonempty); END Send; PROCEDURERecv (self: T): Elem.T = VAR result: Elem.T; BEGIN Debug.S("Channel receiving",DebugLevel); LOCK self.m DO Debug.S("Recv got lock: waiting for nonempty",DebugLevel); WHILE NOT self.queue.get(result) DO Thread.Wait(self.m, self.nonempty); END; END; RETURN result; END Recv; BEGIN END Channel.