lemon/bits/alteration_notifier.h
changeset 2188 984870a2dde4
parent 2006 00d59f733817
child 2305 4a2236cc98a0
     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    };