MODULE Stop; (***************************************************************************) (* Copyright (C) Olivetti 1989 *) (* All Rights reserved *) (* *) (* Use and copy of this software and preparation of derivative works based *) (* upon this software are permitted to any person, provided this same *) (* copyright notice and the following Olivetti warranty disclaimer are *) (* included in any copy of the software or any modification thereof or *) (* derivative work therefrom made by any person. *) (* *) (* This software is made available AS IS and Olivetti disclaims all *) (* warranties with respect to this software, whether expressed or implied *) (* under any law, including all implied warranties of merchantibility and *) (* fitness for any purpose. In no event shall Olivetti be liable for any *) (* damages whatsoever resulting from loss of use, data or profits or *) (* otherwise arising out of or in connection with the use or performance *) (* of this software. *) (***************************************************************************) IMPORT Thread; (* CallBack should be some form of list object but we don't have them yet *) REVEAL CallBack = BRANDED REF RECORD next, prev: CallBack := NIL; closure: Closure; END; VAR mutex_g := Thread.NewMutex(); stopping_g: BOOLEAN := FALSE; closures_g: CallBack := NIL; PROCEDURE Register(closure: Closure): CallBack RAISES {} = VAR new := NEW(CallBack); BEGIN new.closure := closure; LOCK mutex_g DO IF stopping_g THEN RETURN NIL END; new.next := closures_g; IF new.next # NIL THEN new.next.prev := new END; closures_g := new; END; RETURN new; END Register; TYPE BClosure = Closure OBJECT p: Proc OVERRIDES apply := BApply END; PROCEDURE BApply(b: BClosure) RAISES {}= BEGIN b.p(); END BApply; PROCEDURE BasicClosure(p: Proc): Closure RAISES {}= BEGIN RETURN NEW(BClosure, p := p); END BasicClosure; PROCEDURE Cancel(VAR c: CallBack) RAISES {} = BEGIN IF c # NIL THEN LOCK mutex_g DO IF stopping_g OR c = NIL THEN RETURN END; IF c.next # NIL THEN c.next.prev := c.prev END; IF c.prev = NIL AND closures_g = c THEN closures_g := c.next; ELSE c.prev.next := c.next; END; c.next := NIL; c.prev := NIL; c := NIL; END; END; END Cancel; PROCEDURE Stop(code := Code.Good) RAISES {} = VAR closure: CallBack; BEGIN LOCK mutex_g DO IF stopping_g THEN RETURN END; stopping_g := TRUE; closure := closures_g; closures_g := NIL; END; WHILE closure # NIL DO closure.closure.apply(); closure := closure.next; END; Panic(code); END Stop; BEGIN END Stop.