From 343e64cc2c838496ccb07ab7bd58e618cc75036c Mon Sep 17 00:00:00 2001 From: chatty Date: Tue, 28 Nov 2000 14:52:15 +0000 Subject: Added Johnny's criteria Safer destructor --- dnn/Trigger.cc | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 112 insertions(+), 9 deletions(-) (limited to 'dnn') diff --git a/dnn/Trigger.cc b/dnn/Trigger.cc index 9b6db60..3effd6d 100644 --- a/dnn/Trigger.cc +++ b/dnn/Trigger.cc @@ -3,7 +3,7 @@ * * by Stephane Chatty * - * Copyright 1993-1994 + * Copyright 1993-1995 * Centre d'Etudes de la Navigation Aerienne (CENA) * * Event triggers. @@ -14,6 +14,7 @@ #include "Trigger.h" #include "Reaction.h" +#include "Criterion.h" /*?class DnnTrigger \typ{DnnTrigger}s are the core of event detection and emission. The presence of a trigger @@ -28,21 +29,50 @@ the trigger. Create a trigger with an empty list of associated reaction. ?*/ DnnTrigger :: DnnTrigger () -: Subscribers (), - Grabs () +: FirstSubscribers (), + LastSubscribers (), + Subscribers (), + Grabs (), + Criteria () { } /*?nodoc?*/ DnnTrigger :: ~DnnTrigger () { + /* Force reactions to unsubscribe. + We should take care of conditions when destructor is called + during iteration */ + + CcuListIterOf ri = FirstSubscribers; + while (++ri) + (*ri)->Forget (*this); + ri = Subscribers; + while (++ri) + (*ri)->Forget (*this); + ri = LastSubscribers; + while (++ri) + (*ri)->Forget (*this); + ri = Grabs; + while (++ri) + (*ri)->Forget (*this); } /*?nextdoc?*/ void -DnnTrigger :: Subscribe (DnnBaseReaction& a) +DnnTrigger :: Subscribe (DnnBaseReaction& a, REL_PRIORITY p) { - Subscribers.Append (&a); + switch (p) { + case isFirstPriority: + FirstSubscribers.Append (&a); + break; + case isNormalPriority: + Subscribers.Append (&a); + break; + case isLastPriority: + LastSubscribers.Prepend (&a); + break; + } } /*? @@ -52,7 +82,9 @@ events caused by this trigger. void DnnTrigger :: Unsubscribe (DnnBaseReaction& a) { + FirstSubscribers.Remove (&a); Subscribers.Remove (&a); + LastSubscribers.Remove (&a); Grabs.Remove (&a); } @@ -70,8 +102,28 @@ events caused by this trigger. void DnnTrigger :: Release (DnnBaseReaction& a) { - Subscribers.Remove (&a); + Grabs.Remove (&a); +} + +#if 0 +void +DnnTrigger :: Circulate (DnnBaseReaction& r, REL_POS pos, DnnBaseReaction* ref) +{ + + if (Subscribers.Remove (&r)) { + /* find the predecessor of ref */ + CcuListIterOf lc = Subscribers; + while (++lc && (*lc != ref)) + ; + /* NOW, lc is on ref, or at the end if ref == 0 */ + if (pos == isBefore) + Subscribers.InsertBefore (lc, &r); + else + Subscribers.InsertAfter (lc, &r); + } + } +#endif /*? Have a trigger dispatch the event \var{ev} to its associated reactions. @@ -83,9 +135,60 @@ DnnTrigger :: Dispatch (DnnEvent& ev) if (r) { r->Manage (ev); } else { + /* calls to Manage may result in changes in Subscribers; let's make a safe copy */ + CcuListOf first_subscribers = FirstSubscribers; CcuListOf subscribers = Subscribers; - CcuListIterOf ai = subscribers; - while (++ai) - (*ai)->Manage (ev); + CcuListOf last_subscribers = LastSubscribers; + + CcuListIterOf s = first_subscribers; + while (++s) +#ifdef CRITERIA_IN_REACTIONS + if ((*s)->Check (ev)) +#endif + (*s)->Manage (ev); + + s = subscribers; + while (++s) +#ifdef CRITERIA_IN_REACTIONS + if ((*s)->Check (ev)) +#endif + (*s)->Manage (ev); + + s = last_subscribers; + while (++s) +#ifdef CRITERIA_IN_REACTIONS + if ((*s)->Check (ev)) +#endif + (*s)->Manage (ev); } } + + +bool +DnnTrigger :: Check (DnnEvent& ev) +{ + CcuListIterOf c = Criteria; + while (++c) + if (!(*c)->Test (ev)) + return false; + + +#ifdef CRITERIA_IN_REACTIONS + CcuListIterOf ri = FirstSubscribers; + while (++ri) + if ((*ri)->Check (ev)) + return true; + ri = Subscribers; + while (++ri) + if ((*ri)->Check (ev)) + return true; + ri = LastSubscribers; + while (++ri) + if ((*ri)->Check (ev)) + return true; + return false; +#else + return true; +#endif +} + -- cgit v1.1