lemon/bits/alteration_notifier.h
changeset 2333 8070a099ffb6
parent 2188 984870a2dde4
child 2384 805c5a2a36dd
equal deleted inserted replaced
19:3f2c431b4f61 20:1d8a8f01f31e
    18 
    18 
    19 #ifndef LEMON_BITS_ALTERATION_NOTIFIER_H
    19 #ifndef LEMON_BITS_ALTERATION_NOTIFIER_H
    20 #define LEMON_BITS_ALTERATION_NOTIFIER_H
    20 #define LEMON_BITS_ALTERATION_NOTIFIER_H
    21 
    21 
    22 #include <vector>
    22 #include <vector>
       
    23 #include <list>
    23 
    24 
    24 #include <lemon/bits/utility.h>
    25 #include <lemon/bits/utility.h>
    25 
    26 
    26 ///\ingroup graphbits
    27 ///\ingroup graphbits
    27 ///\file
    28 ///\file
   171       /// \brief Attaches the observer into an AlterationNotifier.
   172       /// \brief Attaches the observer into an AlterationNotifier.
   172       ///
   173       ///
   173       /// This member attaches the observer into an AlterationNotifier.
   174       /// This member attaches the observer into an AlterationNotifier.
   174       ///
   175       ///
   175       void attach(AlterationNotifier& _notifier) {
   176       void attach(AlterationNotifier& _notifier) {
   176 	notifier = &_notifier;
   177 	_notifier.attach(*this);
   177 	notifier->attach(*this);
       
   178       }
   178       }
   179       
   179       
   180       /// \brief Detaches the observer into an AlterationNotifier.
   180       /// \brief Detaches the observer into an AlterationNotifier.
   181       ///
   181       ///
   182       /// This member detaches the observer from an AlterationNotifier.
   182       /// This member detaches the observer from an AlterationNotifier.
   201       ObserverBase& operator=(const ObserverBase& copy);
   201       ObserverBase& operator=(const ObserverBase& copy);
   202 
   202 
   203     protected:
   203     protected:
   204       
   204       
   205       Notifier* notifier;
   205       Notifier* notifier;
   206       int notifier_index;
   206       typename std::list<ObserverBase*>::iterator index;
   207 
   207 
   208       /// \brief The member function to notificate the observer about an
   208       /// \brief The member function to notificate the observer about an
   209       /// item is added to the container.
   209       /// item is added to the container.
   210       ///
   210       ///
   211       /// The add() member function notificates the observer about an item
   211       /// The add() member function notificates the observer about an item
   212       /// is added to the container. It have to be overrided in the
   212       /// is added to the container. It have to be overrided in the
   213       /// subclasses.
   213       /// subclasses.
   214 	
       
   215       virtual void add(const Item&) = 0;
   214       virtual void add(const Item&) = 0;
   216 
   215 
   217       /// \brief The member function to notificate the observer about 
   216       /// \brief The member function to notificate the observer about 
   218       /// more item is added to the container.
   217       /// more item is added to the container.
   219       ///
   218       ///
   220       /// The add() member function notificates the observer about more item
   219       /// The add() member function notificates the observer about more item
   221       /// is added to the container. It have to be overrided in the
   220       /// is added to the container. It have to be overrided in the
   222       /// subclasses.
   221       /// subclasses.
   223 
   222       virtual void add(const std::vector<Item>& items) = 0;
   224       virtual void add(const std::vector<Item>& items) {
       
   225         int i;
       
   226         try {
       
   227           for (i = 0; i < (int)items.size(); ++i) {
       
   228             add(items[i]);
       
   229           }
       
   230         } catch (...) {
       
   231           for (int j = 0; j < i; ++j) {
       
   232             add(items[j]);
       
   233           }          
       
   234           throw;
       
   235         }
       
   236       }
       
   237 
   223 
   238       /// \brief The member function to notificate the observer about an
   224       /// \brief The member function to notificate the observer about an
   239       /// item is erased from the container.
   225       /// item is erased from the container.
   240       ///
   226       ///
   241       /// The erase() member function notificates the observer about an
   227       /// The erase() member function notificates the observer about an
   242       /// item is erased from the container. It have to be overrided in
   228       /// item is erased from the container. It have to be overrided in
   243       /// the subclasses.
   229       /// the subclasses.	
   244 	
       
   245       virtual void erase(const Item&) = 0;
   230       virtual void erase(const Item&) = 0;
   246 
   231 
   247       /// \brief The member function to notificate the observer about 
   232       /// \brief The member function to notificate the observer about 
   248       /// more item is erased from the container.
   233       /// more item is erased from the container.
   249       ///
   234       ///
   250       /// The erase() member function notificates the observer about more item
   235       /// The erase() member function notificates the observer about more item
   251       /// is erased from the container. It have to be overrided in the
   236       /// is erased from the container. It have to be overrided in the
   252       /// subclasses.
   237       /// subclasses.
   253       virtual void erase(const std::vector<Item>& items) {
   238       virtual void erase(const std::vector<Item>& items) = 0;
   254         for (int i = 0; i < (int)items.size(); ++i) {
       
   255           erase(items[i]);
       
   256         }
       
   257       }
       
   258 
   239 
   259       /// \brief The member function to notificate the observer about the
   240       /// \brief The member function to notificate the observer about the
   260       /// container is built.
   241       /// container is built.
   261       ///
   242       ///
   262       /// The build() member function notificates the observer about the
   243       /// The build() member function notificates the observer about the
   263       /// container is built from an empty container. It have to be
   244       /// container is built from an empty container. It have to be
   264       /// overrided in the subclasses.
   245       /// overrided in the subclasses.
   265 
   246 
   266       virtual void build() {
   247       virtual void build() = 0;
   267         Item it;
       
   268         try {
       
   269           for (notifier->first(it); it != INVALID; notifier->next(it)) {
       
   270             add(it);
       
   271           }
       
   272         } catch (...) {
       
   273           Item jt;
       
   274           for (notifier->first(jt); jt != it; notifier->next(jt)) {
       
   275             erase(jt);
       
   276           }
       
   277           throw;
       
   278         }
       
   279       }
       
   280 
   248 
   281       /// \brief The member function to notificate the observer about all
   249       /// \brief The member function to notificate the observer about all
   282       /// items are erased from the container.
   250       /// items are erased from the container.
   283       ///
   251       ///
   284       /// The clear() member function notificates the observer about all
   252       /// The clear() member function notificates the observer about all
   285       /// items are erased from the container. It have to be overrided in
   253       /// items are erased from the container. It have to be overrided in
   286       /// the subclasses.      
   254       /// the subclasses.      
   287       virtual void clear() {
   255       virtual void clear() = 0;
   288         Item it;
       
   289         for (notifier->first(it); it != INVALID; notifier->next(it)) {
       
   290           erase(it);
       
   291         }
       
   292       }
       
   293 
   256 
   294     };
   257     };
   295 	
   258 	
   296   protected:
   259   protected:
   297 
   260 
   298     const Container* container;
   261     const Container* container;
   299 
   262 
   300     typedef std::vector<ObserverBase*> Observers; 
   263     typedef std::list<ObserverBase*> Observers; 
   301     Observers observers;
   264     Observers observers;
   302 
   265 
   303 		
   266 		
   304   public:
   267   public:
   305 
   268 
   381     }
   344     }
   382 		
   345 		
   383   protected:
   346   protected:
   384 
   347 
   385     void attach(ObserverBase& observer) {
   348     void attach(ObserverBase& observer) {
   386       observers.push_back(&observer);
   349       observer.index = observers.insert(observers.begin(), &observer);
   387       observer.notifier = this;
   350       observer.notifier = this;
   388       observer.notifier_index = observers.size() - 1;
       
   389     } 
   351     } 
   390 
   352 
   391     void detach(ObserverBase& observer) {
   353     void detach(ObserverBase& observer) {
   392       observers.back()->notifier_index = observer.notifier_index; 
   354       observers.erase(observer.index);
   393       observers[observer.notifier_index] = observers.back();
   355       observer.index = observers.end();
   394       observers.pop_back();
       
   395       observer.notifier = 0;
   356       observer.notifier = 0;
   396     }
   357     }
   397 
   358 
   398   public:
   359   public:
   399 	
   360 	
   402     ///
   363     ///
   403     /// It notifies all the registed observers about an item added to 
   364     /// It notifies all the registed observers about an item added to 
   404     /// the container.
   365     /// the container.
   405     /// 
   366     /// 
   406     void add(const Item& item) {
   367     void add(const Item& item) {
   407       typename Observers::iterator it;
   368       typename Observers::reverse_iterator it;
   408       try {
   369       try {
   409         for (it = observers.begin(); it != observers.end(); ++it) {
   370         for (it = observers.rbegin(); it != observers.rend(); ++it) {
   410           (*it)->add(item);
   371           (*it)->add(item);
   411         }
   372         }
   412       } catch (...) {
   373       } catch (...) {
   413         typename Observers::iterator jt;
   374         typename Observers::iterator jt;
   414         for (jt = observers.begin(); jt != it; ++jt) {
   375         for (jt = it.base(); jt != observers.end(); ++jt) {
   415           (*it)->erase(item);
   376           (*jt)->erase(item);
   416         }
   377         }
   417         throw;
   378         throw;
   418       }
   379       }
   419     }	
   380     }	
   420 
   381 
   423     ///
   384     ///
   424     /// It notifies all the registed observers about more item added to 
   385     /// It notifies all the registed observers about more item added to 
   425     /// the container.
   386     /// the container.
   426     /// 
   387     /// 
   427     void add(const std::vector<Item>& items) {
   388     void add(const std::vector<Item>& items) {
   428       typename Observers::iterator it;
   389       typename Observers::reverse_iterator it;
   429       try {
   390       try {
   430         for (it = observers.begin(); it != observers.end(); ++it) {
   391         for (it = observers.rbegin(); it != observers.rend(); ++it) {
   431           (*it)->add(items);
   392           (*it)->add(items);
   432         }
   393         }
   433       } catch (...) {
   394       } catch (...) {
   434         typename Observers::iterator jt;
   395         typename Observers::iterator jt;
   435         for (jt = observers.begin(); jt != it; ++jt) {
   396         for (jt = it.base(); jt != observers.end(); ++jt) {
   436           (*it)->erase(items);
   397           (*jt)->erase(items);
   437         }
   398         }
   438         throw;
   399         throw;
   439       }
   400       }
   440     }	
   401     }	
   441 
   402 
   443     /// the container.
   404     /// the container.
   444     ///	
   405     ///	
   445     /// It notifies all the registed observers about an item erased from 
   406     /// It notifies all the registed observers about an item erased from 
   446     /// the container.
   407     /// the container.
   447     /// 
   408     /// 
   448     void erase(const Item& key) throw() {
   409     void erase(const Item& item) throw() {
   449       int i = 0;
   410       typename Observers::iterator it = observers.begin();
   450       while (i != (int)observers.size()) {
   411       while (it != observers.end()) {
   451         try {
   412         try {
   452           observers[i]->erase(key);
   413           (*it)->erase(item);
   453           ++i;
   414           ++it;
   454         } catch (const ImmediateDetach&) {
   415         } catch (const ImmediateDetach&) {
   455           observers[i]->detach();
   416           it = observers.erase(it);
       
   417           (*it)->index = observers.end();
       
   418           (*it)->notifier = 0;
   456         }
   419         }
   457       }
   420       }
   458     }
   421     }
   459 
   422 
   460     /// \brief Notifies all the registed observers about more item erased  
   423     /// \brief Notifies all the registed observers about more item erased  
   462     ///	
   425     ///	
   463     /// It notifies all the registed observers about more item erased from 
   426     /// It notifies all the registed observers about more item erased from 
   464     /// the container.
   427     /// the container.
   465     /// 
   428     /// 
   466     void erase(const std::vector<Item>& items) {
   429     void erase(const std::vector<Item>& items) {
   467       int i = 0;
   430       typename Observers::iterator it = observers.begin();
   468       while (i != (int)observers.size()) {
   431       while (it != observers.end()) {
   469         try {
   432         try {
   470           observers[i]->erase(items);
   433           (*it)->erase(items);
   471           ++i;
   434           ++it;
   472         } catch (const ImmediateDetach&) {
   435         } catch (const ImmediateDetach&) {
   473           observers[i]->detach();
   436           it = observers.erase(it);
       
   437           (*it)->index = observers.end();
       
   438           (*it)->notifier = 0;
   474         }
   439         }
   475       }
   440       }
   476     }
   441     }
   477 
   442 
   478     /// \brief Notifies all the registed observers about the container is 
   443     /// \brief Notifies all the registed observers about the container is 
   479     /// built.
   444     /// built.
   480     ///		
   445     ///		
   481     /// Notifies all the registed observers about the container is built
   446     /// Notifies all the registed observers about the container is built
   482     /// from an empty container.
   447     /// from an empty container.
   483     void build() {
   448     void build() {
   484       typename Observers::iterator it;
   449       typename Observers::reverse_iterator it;
   485       try {
   450       try {
   486         for (it = observers.begin(); it != observers.end(); ++it) {
   451         for (it = observers.rbegin(); it != observers.rend(); ++it) {
   487           (*it)->build();
   452           (*it)->build();
   488         }
   453         }
   489       } catch (...) {
   454       } catch (...) {
   490         typename Observers::iterator jt;
   455         typename Observers::iterator jt;
   491         for (jt = observers.begin(); jt != it; ++jt) {
   456         for (jt = it.base(); jt != observers.end(); ++jt) {
   492           (*it)->clear();
   457           (*jt)->clear();
   493         }
   458         }
   494         throw;
   459         throw;
   495       }
   460       }
   496     }
   461     }
   497 
   462 
   499     /// erased.
   464     /// erased.
   500     ///
   465     ///
   501     /// Notifies all the registed observers about all items are erased
   466     /// Notifies all the registed observers about all items are erased
   502     /// from the container.
   467     /// from the container.
   503     void clear() {
   468     void clear() {
   504       int i = 0;
   469       typename Observers::iterator it = observers.begin();
   505       while (i != (int)observers.size()) {
   470       while (it != observers.end()) {
   506         try {
   471         try {
   507           observers[i]->clear();
   472           (*it)->clear();
   508           ++i;
   473           ++it;
   509         } catch (const ImmediateDetach&) {
   474         } catch (const ImmediateDetach&) {
   510           observers[i]->detach();
   475           it = observers.erase(it);
       
   476           (*it)->index = observers.end();
       
   477           (*it)->notifier = 0;
   511         }
   478         }
   512       }
   479       }
   513     }
   480     }
   514   };
   481   };
   515 
   482