GENERIC MODULECBStack (AnyCB); IMPORT CB, GO; REVEAL T = Public BRANDED OBJECT mu : MUTEX; list : List; OVERRIDES init := Init; invokeTop := InvokeTop; push := Push; pop := Pop; remove := Remove; END; TYPE List = REF RECORD head : AnyCB.T; tail : List; END; PROCEDUREInit (self : T) : T = BEGIN self.list := NIL; self.mu := NEW (MUTEX); RETURN self; END Init; PROCEDUREInvokeTop (self : T; rec : AnyCB.Rec) RAISES {CB.BadMethod} = VAR top : AnyCB.T; BEGIN LOCK self.mu DO IF self.list # NIL THEN top := self.list.head; END; END; IF top # NIL THEN top.invoke (rec); END; END InvokeTop; PROCEDUREPush (self : T; cb : AnyCB.T) = BEGIN LOCK self.mu DO self.list := NEW (List, head := cb, tail := self.list); END; END Push; PROCEDUREPop (self : T) RAISES {GO.StackError} = BEGIN LOCK self.mu DO IF self.list = NIL THEN RAISE GO.StackError; ELSE self.list := self.list.tail; END; END; END Pop; PROCEDURERemove (self : T; cb : AnyCB.T) RAISES {GO.StackError} = PROCEDURE Remove (VAR list : List) RAISES {GO.StackError} = BEGIN IF list = NIL THEN RAISE GO.StackError; ELSIF list.head = cb THEN list := list.tail; ELSE Remove (list.tail); END; END Remove; BEGIN LOCK self.mu DO Remove (self.list); END; END Remove; BEGIN END CBStack.