[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