lemon/bits/alteration_notifier.h
changeset 2191 ef3560193856
parent 2006 00d59f733817
child 2305 4a2236cc98a0
equal deleted inserted replaced
18:a3580c87715f 19:3f2c431b4f61
    64   /// them from the container, on the other way on item addition we should
    64   /// them from the container, on the other way on item addition we should
    65   /// first extend the container and just after that signal the alteration.
    65   /// first extend the container and just after that signal the alteration.
    66   ///
    66   ///
    67   /// The alteration can be observed with a class inherited from the
    67   /// The alteration can be observed with a class inherited from the
    68   /// \e ObserverBase nested class. The signals can be handled with
    68   /// \e ObserverBase nested class. The signals can be handled with
    69   /// overriding the virtual functions defined in the base class.
    69   /// overriding the virtual functions defined in the base class.  The
    70   /// The observer base can be attached to the notifier with the
    70   /// observer base can be attached to the notifier with the 
    71   /// \e attach() member and can be detached with detach() function.
    71   /// \e attach() member and can be detached with detach() function. The
    72   ///
    72   /// alteration handlers should not call any function which signals
    73   /// Alteration observers try to be exception safe. This can be achived
    73   /// an other alteration in the same notifier and should not
    74   /// when the observers does not throw exception on \e erase() and 
    74   /// detach any observer from the notifier.
    75   /// \e clear(). Less strict condition is that the \e erase() should
    75   ///
    76   /// not throw exception after an \e add() with the same parameter and
    76   /// Alteration observers try to be exception safe. If an \e add() or
    77   /// the \e clear() should not throw exception after a \e build(). 
    77   /// a \e clear() function throws an exception then the remaining
       
    78   /// observeres will not be notified and the fulfilled additions will
       
    79   /// be rolled back by calling the \e erase() or \e clear()
       
    80   /// functions. Thence the \e erase() and \e clear() should not throw
       
    81   /// exception. Actullay, it can be throw only 
       
    82   /// \ref AlterationObserver::ImmediateDetach ImmediateDetach
       
    83   /// exception which detach the observer from the notifier.
    78   ///
    84   ///
    79   /// There are some place when the alteration observing is not completly
    85   /// There are some place when the alteration observing is not completly
    80   /// reliable. If we want to carry out the node degree in the graph
    86   /// reliable. If we want to carry out the node degree in the graph
    81   /// as in the \ref InDegMap and we use the reverseEdge that cause 
    87   /// as in the \ref InDegMap and we use the reverseEdge that cause 
    82   /// unreliable functionality. Because the alteration observing signals
    88   /// unreliable functionality. Because the alteration observing signals
    97     typedef True Notifier;
   103     typedef True Notifier;
    98 
   104 
    99     typedef _Container Container;
   105     typedef _Container Container;
   100     typedef _Item Item;
   106     typedef _Item Item;
   101 
   107 
       
   108     /// \brief Exception which can be called from \e clear() and 
       
   109     /// \e erase().
       
   110     ///
       
   111     /// From the \e clear() and \e erase() function only this
       
   112     /// exception is allowed to throw. The exception immediatly
       
   113     /// detaches the current observer from the notifier. Because the
       
   114     /// \e clear() and \e erase() should not throw other exceptions
       
   115     /// it can be used to invalidate the observer.
       
   116     struct ImmediateDetach {};
       
   117 
   102     /// \brief ObserverBase is the base class for the observers.
   118     /// \brief ObserverBase is the base class for the observers.
   103     ///
   119     ///
   104     /// ObserverBase is the abstract base class for the observers.
   120     /// ObserverBase is the abstract base class for the observers.
   105     /// It will be notified about an item was inserted into or
   121     /// It will be notified about an item was inserted into or
   106     /// erased from the graph.
   122     /// erased from the graph.
   158       ///
   174       ///
   159       void attach(AlterationNotifier& _notifier) {
   175       void attach(AlterationNotifier& _notifier) {
   160 	notifier = &_notifier;
   176 	notifier = &_notifier;
   161 	notifier->attach(*this);
   177 	notifier->attach(*this);
   162       }
   178       }
   163 
   179       
   164       /// \brief Detaches the observer into an AlterationNotifier.
   180       /// \brief Detaches the observer into an AlterationNotifier.
   165       ///
   181       ///
   166       /// This member detaches the observer from an AlterationNotifier.
   182       /// This member detaches the observer from an AlterationNotifier.
   167       ///
   183       ///
   168       void detach() {
   184       void detach() {
   169         notifier->detach(*this);
   185         notifier->detach(*this);
   170       }
   186       }
   171 	
   187       
   172 
       
   173       /// \brief Gives back a pointer to the notifier which the map 
   188       /// \brief Gives back a pointer to the notifier which the map 
   174       /// attached into.
   189       /// attached into.
   175       ///
   190       ///
   176       /// This function gives back a pointer to the notifier which the map
   191       /// This function gives back a pointer to the notifier which the map
   177       /// attached into.
   192       /// attached into.
   428     /// the container.
   443     /// the container.
   429     ///	
   444     ///	
   430     /// It notifies all the registed observers about an item erased from 
   445     /// It notifies all the registed observers about an item erased from 
   431     /// the container.
   446     /// the container.
   432     /// 
   447     /// 
   433     void erase(const Item& key) {
   448     void erase(const Item& key) throw() {
   434       typename Observers::iterator it;
   449       int i = 0;
   435       for (it = observers.begin(); it != observers.end(); ++it) {
   450       while (i != (int)observers.size()) {
   436 	(*it)->erase(key);
   451         try {
       
   452           observers[i]->erase(key);
       
   453           ++i;
       
   454         } catch (const ImmediateDetach&) {
       
   455           observers[i]->detach();
       
   456         }
   437       }
   457       }
   438     }
   458     }
   439 
   459 
   440     /// \brief Notifies all the registed observers about more item erased  
   460     /// \brief Notifies all the registed observers about more item erased  
   441     /// from the container.
   461     /// from the container.
   442     ///	
   462     ///	
   443     /// It notifies all the registed observers about more item erased from 
   463     /// It notifies all the registed observers about more item erased from 
   444     /// the container.
   464     /// the container.
   445     /// 
   465     /// 
   446     void erase(const std::vector<Item>& items) {
   466     void erase(const std::vector<Item>& items) {
   447       typename Observers::iterator it;
   467       int i = 0;
   448       for (it = observers.begin(); it != observers.end(); ++it) {
   468       while (i != (int)observers.size()) {
   449 	(*it)->erase(items);
   469         try {
       
   470           observers[i]->erase(items);
       
   471           ++i;
       
   472         } catch (const ImmediateDetach&) {
       
   473           observers[i]->detach();
       
   474         }
   450       }
   475       }
   451     }
   476     }
   452 
   477 
   453     /// \brief Notifies all the registed observers about the container is 
   478     /// \brief Notifies all the registed observers about the container is 
   454     /// built.
   479     /// built.
   468         }
   493         }
   469         throw;
   494         throw;
   470       }
   495       }
   471     }
   496     }
   472 
   497 
   473 
       
   474     /// \brief Notifies all the registed observers about all items are 
   498     /// \brief Notifies all the registed observers about all items are 
   475     /// erased.
   499     /// erased.
   476     ///
   500     ///
   477     /// Notifies all the registed observers about all items are erased
   501     /// Notifies all the registed observers about all items are erased
   478     /// from the container.
   502     /// from the container.
   479     void clear() {
   503     void clear() {
   480       typename Observers::iterator it;
   504       int i = 0;
   481       for (it = observers.begin(); it != observers.end(); ++it) {
   505       while (i != (int)observers.size()) {
   482 	(*it)->clear();
   506         try {
       
   507           observers[i]->clear();
       
   508           ++i;
       
   509         } catch (const ImmediateDetach&) {
       
   510           observers[i]->detach();
       
   511         }
   483       }
   512       }
   484     }
   513     }
   485   };
   514   };
   486 
   515 
   487 }
   516 }