1.1 --- a/lemon/bits/alteration_notifier.h Mon Sep 04 11:02:31 2006 +0000
1.2 +++ b/lemon/bits/alteration_notifier.h Mon Sep 04 11:05:21 2006 +0000
1.3 @@ -66,15 +66,21 @@
1.4 ///
1.5 /// The alteration can be observed with a class inherited from the
1.6 /// \e ObserverBase nested class. The signals can be handled with
1.7 - /// overriding the virtual functions defined in the base class.
1.8 - /// The observer base can be attached to the notifier with the
1.9 - /// \e attach() member and can be detached with detach() function.
1.10 + /// overriding the virtual functions defined in the base class. The
1.11 + /// observer base can be attached to the notifier with the
1.12 + /// \e attach() member and can be detached with detach() function. The
1.13 + /// alteration handlers should not call any function which signals
1.14 + /// an other alteration in the same notifier and should not
1.15 + /// detach any observer from the notifier.
1.16 ///
1.17 - /// Alteration observers try to be exception safe. This can be achived
1.18 - /// when the observers does not throw exception on \e erase() and
1.19 - /// \e clear(). Less strict condition is that the \e erase() should
1.20 - /// not throw exception after an \e add() with the same parameter and
1.21 - /// the \e clear() should not throw exception after a \e build().
1.22 + /// Alteration observers try to be exception safe. If an \e add() or
1.23 + /// a \e clear() function throws an exception then the remaining
1.24 + /// observeres will not be notified and the fulfilled additions will
1.25 + /// be rolled back by calling the \e erase() or \e clear()
1.26 + /// functions. Thence the \e erase() and \e clear() should not throw
1.27 + /// exception. Actullay, it can be throw only
1.28 + /// \ref AlterationObserver::ImmediateDetach ImmediateDetach
1.29 + /// exception which detach the observer from the notifier.
1.30 ///
1.31 /// There are some place when the alteration observing is not completly
1.32 /// reliable. If we want to carry out the node degree in the graph
1.33 @@ -99,6 +105,16 @@
1.34 typedef _Container Container;
1.35 typedef _Item Item;
1.36
1.37 + /// \brief Exception which can be called from \e clear() and
1.38 + /// \e erase().
1.39 + ///
1.40 + /// From the \e clear() and \e erase() function only this
1.41 + /// exception is allowed to throw. The exception immediatly
1.42 + /// detaches the current observer from the notifier. Because the
1.43 + /// \e clear() and \e erase() should not throw other exceptions
1.44 + /// it can be used to invalidate the observer.
1.45 + struct ImmediateDetach {};
1.46 +
1.47 /// \brief ObserverBase is the base class for the observers.
1.48 ///
1.49 /// ObserverBase is the abstract base class for the observers.
1.50 @@ -160,7 +176,7 @@
1.51 notifier = &_notifier;
1.52 notifier->attach(*this);
1.53 }
1.54 -
1.55 +
1.56 /// \brief Detaches the observer into an AlterationNotifier.
1.57 ///
1.58 /// This member detaches the observer from an AlterationNotifier.
1.59 @@ -168,8 +184,7 @@
1.60 void detach() {
1.61 notifier->detach(*this);
1.62 }
1.63 -
1.64 -
1.65 +
1.66 /// \brief Gives back a pointer to the notifier which the map
1.67 /// attached into.
1.68 ///
1.69 @@ -430,10 +445,15 @@
1.70 /// It notifies all the registed observers about an item erased from
1.71 /// the container.
1.72 ///
1.73 - void erase(const Item& key) {
1.74 - typename Observers::iterator it;
1.75 - for (it = observers.begin(); it != observers.end(); ++it) {
1.76 - (*it)->erase(key);
1.77 + void erase(const Item& key) throw() {
1.78 + int i = 0;
1.79 + while (i != (int)observers.size()) {
1.80 + try {
1.81 + observers[i]->erase(key);
1.82 + ++i;
1.83 + } catch (const ImmediateDetach&) {
1.84 + observers[i]->detach();
1.85 + }
1.86 }
1.87 }
1.88
1.89 @@ -444,9 +464,14 @@
1.90 /// the container.
1.91 ///
1.92 void erase(const std::vector<Item>& items) {
1.93 - typename Observers::iterator it;
1.94 - for (it = observers.begin(); it != observers.end(); ++it) {
1.95 - (*it)->erase(items);
1.96 + int i = 0;
1.97 + while (i != (int)observers.size()) {
1.98 + try {
1.99 + observers[i]->erase(items);
1.100 + ++i;
1.101 + } catch (const ImmediateDetach&) {
1.102 + observers[i]->detach();
1.103 + }
1.104 }
1.105 }
1.106
1.107 @@ -470,16 +495,20 @@
1.108 }
1.109 }
1.110
1.111 -
1.112 /// \brief Notifies all the registed observers about all items are
1.113 /// erased.
1.114 ///
1.115 /// Notifies all the registed observers about all items are erased
1.116 /// from the container.
1.117 void clear() {
1.118 - typename Observers::iterator it;
1.119 - for (it = observers.begin(); it != observers.end(); ++it) {
1.120 - (*it)->clear();
1.121 + int i = 0;
1.122 + while (i != (int)observers.size()) {
1.123 + try {
1.124 + observers[i]->clear();
1.125 + ++i;
1.126 + } catch (const ImmediateDetach&) {
1.127 + observers[i]->detach();
1.128 + }
1.129 }
1.130 }
1.131 };