[Lemon-commits] [lemon_svn] deba: r2913 - hugo/trunk/lemon/bits

Lemon SVN svn at lemon.cs.elte.hu
Mon Nov 6 21:51:12 CET 2006


Author: deba
Date: Mon Sep  4 13:05:21 2006
New Revision: 2913

Modified:
   hugo/trunk/lemon/bits/alteration_notifier.h

Log:
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



Modified: hugo/trunk/lemon/bits/alteration_notifier.h
==============================================================================
--- hugo/trunk/lemon/bits/alteration_notifier.h	(original)
+++ hugo/trunk/lemon/bits/alteration_notifier.h	Mon Sep  4 13:05:21 2006
@@ -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<Item>& 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();
+        }
       }
     }
   };



More information about the Lemon-commits mailing list