# HG changeset patch # User deba # Date 1164130088 0 # Node ID 4a2236cc98a03a1f2b37a09f3e53a7f0d60f6ebc # Parent 108d6db4f32a7cdf4232e521c8ff073d255a1cd0 Keeping order of alteration observers Removing some automatic callback generation // exception safety reason diff -r 108d6db4f32a -r 4a2236cc98a0 lemon/bits/alteration_notifier.h --- a/lemon/bits/alteration_notifier.h Mon Nov 20 10:14:21 2006 +0000 +++ b/lemon/bits/alteration_notifier.h Tue Nov 21 17:28:08 2006 +0000 @@ -20,6 +20,7 @@ #define LEMON_BITS_ALTERATION_NOTIFIER_H #include +#include #include @@ -173,8 +174,7 @@ /// This member attaches the observer into an AlterationNotifier. /// void attach(AlterationNotifier& _notifier) { - notifier = &_notifier; - notifier->attach(*this); + _notifier.attach(*this); } /// \brief Detaches the observer into an AlterationNotifier. @@ -203,7 +203,7 @@ protected: Notifier* notifier; - int notifier_index; + typename std::list::iterator index; /// \brief The member function to notificate the observer about an /// item is added to the container. @@ -211,7 +211,6 @@ /// The add() member function notificates the observer about an item /// is added to the container. It have to be overrided in the /// subclasses. - virtual void add(const Item&) = 0; /// \brief The member function to notificate the observer about @@ -220,28 +219,14 @@ /// The add() member function notificates the observer about more item /// is added to the container. It have to be overrided in the /// subclasses. - - virtual void add(const std::vector& items) { - int i; - try { - for (i = 0; i < (int)items.size(); ++i) { - add(items[i]); - } - } catch (...) { - for (int j = 0; j < i; ++j) { - add(items[j]); - } - throw; - } - } + virtual void add(const std::vector& items) = 0; /// \brief The member function to notificate the observer about an /// item is erased from the container. /// /// The erase() member function notificates the observer about an /// item is erased from the container. It have to be overrided in - /// the subclasses. - + /// the subclasses. virtual void erase(const Item&) = 0; /// \brief The member function to notificate the observer about @@ -250,11 +235,7 @@ /// The erase() member function notificates the observer about more item /// is erased from the container. It have to be overrided in the /// subclasses. - virtual void erase(const std::vector& items) { - for (int i = 0; i < (int)items.size(); ++i) { - erase(items[i]); - } - } + virtual void erase(const std::vector& items) = 0; /// \brief The member function to notificate the observer about the /// container is built. @@ -263,20 +244,7 @@ /// container is built from an empty container. It have to be /// overrided in the subclasses. - virtual void build() { - Item it; - try { - for (notifier->first(it); it != INVALID; notifier->next(it)) { - add(it); - } - } catch (...) { - Item jt; - for (notifier->first(jt); jt != it; notifier->next(jt)) { - erase(jt); - } - throw; - } - } + virtual void build() = 0; /// \brief The member function to notificate the observer about all /// items are erased from the container. @@ -284,12 +252,7 @@ /// The clear() member function notificates the observer about all /// items are erased from the container. It have to be overrided in /// the subclasses. - virtual void clear() { - Item it; - for (notifier->first(it); it != INVALID; notifier->next(it)) { - erase(it); - } - } + virtual void clear() = 0; }; @@ -297,7 +260,7 @@ const Container* container; - typedef std::vector Observers; + typedef std::list Observers; Observers observers; @@ -383,15 +346,13 @@ protected: void attach(ObserverBase& observer) { - observers.push_back(&observer); + observer.index = observers.insert(observers.begin(), &observer); observer.notifier = this; - observer.notifier_index = observers.size() - 1; } void detach(ObserverBase& observer) { - observers.back()->notifier_index = observer.notifier_index; - observers[observer.notifier_index] = observers.back(); - observers.pop_back(); + observers.erase(observer.index); + observer.index = observers.end(); observer.notifier = 0; } @@ -404,15 +365,15 @@ /// the container. /// void add(const Item& item) { - typename Observers::iterator it; + typename Observers::reverse_iterator it; try { - for (it = observers.begin(); it != observers.end(); ++it) { + for (it = observers.rbegin(); it != observers.rend(); ++it) { (*it)->add(item); } } catch (...) { typename Observers::iterator jt; - for (jt = observers.begin(); jt != it; ++jt) { - (*it)->erase(item); + for (jt = it.base(); jt != observers.end(); ++jt) { + (*jt)->erase(item); } throw; } @@ -425,15 +386,15 @@ /// the container. /// void add(const std::vector& items) { - typename Observers::iterator it; + typename Observers::reverse_iterator it; try { - for (it = observers.begin(); it != observers.end(); ++it) { + for (it = observers.rbegin(); it != observers.rend(); ++it) { (*it)->add(items); } } catch (...) { typename Observers::iterator jt; - for (jt = observers.begin(); jt != it; ++jt) { - (*it)->erase(items); + for (jt = it.base(); jt != observers.end(); ++jt) { + (*jt)->erase(items); } throw; } @@ -445,14 +406,16 @@ /// It notifies all the registed observers about an item erased from /// the container. /// - void erase(const Item& key) throw() { - int i = 0; - while (i != (int)observers.size()) { + void erase(const Item& item) throw() { + typename Observers::iterator it = observers.begin(); + while (it != observers.end()) { try { - observers[i]->erase(key); - ++i; + (*it)->erase(item); + ++it; } catch (const ImmediateDetach&) { - observers[i]->detach(); + it = observers.erase(it); + (*it)->index = observers.end(); + (*it)->notifier = 0; } } } @@ -464,13 +427,15 @@ /// the container. /// void erase(const std::vector& items) { - int i = 0; - while (i != (int)observers.size()) { + typename Observers::iterator it = observers.begin(); + while (it != observers.end()) { try { - observers[i]->erase(items); - ++i; + (*it)->erase(items); + ++it; } catch (const ImmediateDetach&) { - observers[i]->detach(); + it = observers.erase(it); + (*it)->index = observers.end(); + (*it)->notifier = 0; } } } @@ -481,15 +446,15 @@ /// Notifies all the registed observers about the container is built /// from an empty container. void build() { - typename Observers::iterator it; + typename Observers::reverse_iterator it; try { - for (it = observers.begin(); it != observers.end(); ++it) { + for (it = observers.rbegin(); it != observers.rend(); ++it) { (*it)->build(); } } catch (...) { typename Observers::iterator jt; - for (jt = observers.begin(); jt != it; ++jt) { - (*it)->clear(); + for (jt = it.base(); jt != observers.end(); ++jt) { + (*jt)->clear(); } throw; } @@ -501,13 +466,15 @@ /// Notifies all the registed observers about all items are erased /// from the container. void clear() { - int i = 0; - while (i != (int)observers.size()) { + typename Observers::iterator it = observers.begin(); + while (it != observers.end()) { try { - observers[i]->clear(); - ++i; + (*it)->clear(); + ++it; } catch (const ImmediateDetach&) { - observers[i]->detach(); + it = observers.erase(it); + (*it)->index = observers.end(); + (*it)->notifier = 0; } } } diff -r 108d6db4f32a -r 4a2236cc98a0 lemon/matrix_maps.h --- a/lemon/matrix_maps.h Mon Nov 20 10:14:21 2006 +0000 +++ b/lemon/matrix_maps.h Tue Nov 21 17:28:08 2006 +0000 @@ -354,8 +354,22 @@ } } + virtual void add(const std::vector& keys) { + int new_size = 0; + for (int i = 0; i < (int)keys.size(); ++i) { + if (size(Parent::getNotifier()->id(keys[i]) + 1) >= new_size) { + new_size = size(Parent::getNotifier()->id(keys[i]) + 1); + } + } + if (new_size > (int)values.size()) { + values.resize(new_size); + } + } + virtual void erase(const Key&) {} + virtual void erase(const std::vector&) {} + virtual void build() { values.resize(size(Parent::getNotifier()->maxId() + 1)); } @@ -495,8 +509,22 @@ } } + virtual void add(const std::vector& keys) { + int new_size = 0; + for (int i = 0; i < (int)keys.size(); ++i) { + if (size(Parent::getNotifier()->id(keys[i]) + 1) >= new_size) { + new_size = size(Parent::getNotifier()->id(keys[i]) + 1); + } + } + if (new_size > (int)values.size()) { + values.resize(new_size); + } + } + virtual void erase(const Key&) {} + virtual void erase(const std::vector&) {} + virtual void build() { values.resize(size(Parent::getNotifier()->maxId() + 1)); }