# HG changeset patch # User deba # Date 1157367921 0 # Node ID 984870a2dde4c45e3cc3a23b94d2e0e5f8b2ca6d # Parent a54a2dd03f036194056ddf5f295dac5f6dda03a4 Improvment in exception handling The erase and clear handlers have to be exception safe. These can throw only one exception which detach the observer from the notifier diff -r a54a2dd03f03 -r 984870a2dde4 lemon/bits/alteration_notifier.h --- a/lemon/bits/alteration_notifier.h Mon Sep 04 11:02:31 2006 +0000 +++ b/lemon/bits/alteration_notifier.h Mon Sep 04 11:05:21 2006 +0000 @@ -66,15 +66,21 @@ /// /// The alteration can be observed with a class inherited from the /// \e ObserverBase nested class. The signals can be handled with - /// overriding the virtual functions defined in the base class. - /// The observer base can be attached to the notifier with the - /// \e attach() member and can be detached with detach() function. + /// overriding the virtual functions defined in the base class. The + /// observer base can be attached to the notifier with the + /// \e attach() member and can be detached with detach() function. The + /// alteration handlers should not call any function which signals + /// an other alteration in the same notifier and should not + /// detach any observer from the notifier. /// - /// Alteration observers try to be exception safe. This can be achived - /// when the observers does not throw exception on \e erase() and - /// \e clear(). Less strict condition is that the \e erase() should - /// not throw exception after an \e add() with the same parameter and - /// the \e clear() should not throw exception after a \e build(). + /// Alteration observers try to be exception safe. If an \e add() or + /// a \e clear() function throws an exception then the remaining + /// observeres will not be notified and the fulfilled additions will + /// be rolled back by calling the \e erase() or \e clear() + /// functions. Thence the \e erase() and \e clear() should not throw + /// exception. Actullay, it can be throw only + /// \ref AlterationObserver::ImmediateDetach ImmediateDetach + /// exception which detach the observer from the notifier. /// /// There are some place when the alteration observing is not completly /// reliable. If we want to carry out the node degree in the graph @@ -99,6 +105,16 @@ typedef _Container Container; typedef _Item Item; + /// \brief Exception which can be called from \e clear() and + /// \e erase(). + /// + /// From the \e clear() and \e erase() function only this + /// exception is allowed to throw. The exception immediatly + /// detaches the current observer from the notifier. Because the + /// \e clear() and \e erase() should not throw other exceptions + /// it can be used to invalidate the observer. + struct ImmediateDetach {}; + /// \brief ObserverBase is the base class for the observers. /// /// ObserverBase is the abstract base class for the observers. @@ -160,7 +176,7 @@ notifier = &_notifier; notifier->attach(*this); } - + /// \brief Detaches the observer into an AlterationNotifier. /// /// This member detaches the observer from an AlterationNotifier. @@ -168,8 +184,7 @@ void detach() { notifier->detach(*this); } - - + /// \brief Gives back a pointer to the notifier which the map /// attached into. /// @@ -430,10 +445,15 @@ /// It notifies all the registed observers about an item erased from /// the container. /// - void erase(const Item& key) { - typename Observers::iterator it; - for (it = observers.begin(); it != observers.end(); ++it) { - (*it)->erase(key); + void erase(const Item& key) throw() { + int i = 0; + while (i != (int)observers.size()) { + try { + observers[i]->erase(key); + ++i; + } catch (const ImmediateDetach&) { + observers[i]->detach(); + } } } @@ -444,9 +464,14 @@ /// the container. /// void erase(const std::vector& items) { - typename Observers::iterator it; - for (it = observers.begin(); it != observers.end(); ++it) { - (*it)->erase(items); + int i = 0; + while (i != (int)observers.size()) { + try { + observers[i]->erase(items); + ++i; + } catch (const ImmediateDetach&) { + observers[i]->detach(); + } } } @@ -470,16 +495,20 @@ } } - /// \brief Notifies all the registed observers about all items are /// erased. /// /// Notifies all the registed observers about all items are erased /// from the container. void clear() { - typename Observers::iterator it; - for (it = observers.begin(); it != observers.end(); ++it) { - (*it)->clear(); + int i = 0; + while (i != (int)observers.size()) { + try { + observers[i]->clear(); + ++i; + } catch (const ImmediateDetach&) { + observers[i]->detach(); + } } } };