Improvment in exception handling
authordeba
Mon, 04 Sep 2006 11:05:21 +0000
changeset 2188984870a2dde4
parent 2187 a54a2dd03f03
child 2189 de2b77e3868c
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
lemon/bits/alteration_notifier.h
     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    };