lemon/bits/alteration_notifier.h
author deba
Mon, 03 Apr 2006 09:45:23 +0000
changeset 2031 080d51024ac5
parent 1999 2ff283124dfc
child 2188 984870a2dde4
permissions -rw-r--r--
Correcting the structure of the graph's and adaptor's map.
The template assign operators and map iterators can be used for adaptors also.

Some bugfix in the adaptors

New class SwapBpUGraphAdaptor which swaps the two nodeset of the graph.
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2006
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 #ifndef LEMON_BITS_ALTERATION_NOTIFIER_H
    20 #define LEMON_BITS_ALTERATION_NOTIFIER_H
    21 
    22 #include <vector>
    23 
    24 #include <lemon/bits/utility.h>
    25 
    26 ///\ingroup graphbits
    27 ///\file
    28 ///\brief Observer notifier for graph alteration observers.
    29 
    30 namespace lemon {
    31 
    32   /// \ingroup graphbits
    33   ///
    34   /// \brief Notifier class to notify observes about alterations in 
    35   /// a container.
    36   ///
    37   /// The simple graph's can be refered as two containers, one node container
    38   /// and one edge container. But they are not standard containers they
    39   /// does not store values directly they are just key continars for more
    40   /// value containers which are the node and edge maps.
    41   ///
    42   /// The graph's node and edge sets can be changed as we add or erase
    43   /// nodes and edges in the graph. Lemon would like to handle easily
    44   /// that the node and edge maps should contain values for all nodes or
    45   /// edges. If we want to check on every indicing if the map contains
    46   /// the current indicing key that cause a drawback in the performance
    47   /// in the library. We use another solution we notify all maps about
    48   /// an alteration in the graph, which cause only drawback on the
    49   /// alteration of the graph.
    50   ///
    51   /// This class provides an interface to the container. The \e first() and \e 
    52   /// next() member functions make possible to iterate on the keys of the
    53   /// container. The \e id() function returns an integer id for each key.
    54   /// The \e maxId() function gives back an upper bound of the ids.
    55   ///
    56   /// For the proper functonality of this class, we should notify it
    57   /// about each alteration in the container. The alterations have four type
    58   /// as \e add(), \e erase(), \e build() and \e clear(). The \e add() and
    59   /// \e erase() signals that only one or few items added or erased to or
    60   /// from the graph. If all items are erased from the graph or from an empty
    61   /// graph a new graph is builded then it can be signaled with the
    62   /// clear() and build() members. Important rule that if we erase items 
    63   /// from graph we should first signal the alteration and after that erase
    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.
    66   ///
    67   /// The alteration can be observed with a class inherited from the
    68   /// \e ObserverBase nested class. The signals can be handled with
    69   /// overriding the virtual functions defined in the base class.
    70   /// The observer base can be attached to the notifier with the
    71   /// \e attach() member and can be detached with detach() function.
    72   ///
    73   /// Alteration observers try to be exception safe. This can be achived
    74   /// when the observers does not throw exception on \e erase() and 
    75   /// \e clear(). Less strict condition is that the \e erase() should
    76   /// not throw exception after an \e add() with the same parameter and
    77   /// the \e clear() should not throw exception after a \e build(). 
    78   ///
    79   /// 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
    81   /// as in the \ref InDegMap and we use the reverseEdge that cause 
    82   /// unreliable functionality. Because the alteration observing signals
    83   /// only erasing and adding but not the reversing it will stores bad
    84   /// degrees. The sub graph adaptors cannot signal the alterations because
    85   /// just a setting in the filter map can modify the graph and this cannot
    86   /// be watched in any way.
    87   ///
    88   /// \param _Container The container which is observed.
    89   /// \param _Item The item type which is obserbved.
    90   ///
    91   /// \author Balazs Dezso
    92 
    93   template <typename _Container, typename _Item>
    94   class AlterationNotifier {
    95   public:
    96 
    97     typedef True Notifier;
    98 
    99     typedef _Container Container;
   100     typedef _Item Item;
   101 
   102     /// \brief ObserverBase is the base class for the observers.
   103     ///
   104     /// ObserverBase is the abstract base class for the observers.
   105     /// It will be notified about an item was inserted into or
   106     /// erased from the graph.
   107     ///
   108     /// The observer interface contains some pure virtual functions
   109     /// to override. The add() and erase() functions are
   110     /// to notify the oberver when one item is added or
   111     /// erased.
   112     ///
   113     /// The build() and clear() members are to notify the observer
   114     /// about the container is built from an empty container or
   115     /// is cleared to an empty container. 
   116     /// 
   117     /// \author Balazs Dezso
   118 
   119     class ObserverBase {
   120     protected:
   121       typedef AlterationNotifier Notifier;
   122 
   123       friend class AlterationNotifier;
   124 
   125       /// \brief Default constructor.
   126       ///
   127       /// Default constructor for ObserverBase.
   128       /// 
   129       ObserverBase() : notifier(0) {}
   130 
   131       /// \brief Constructor which attach the observer into notifier.
   132       ///
   133       /// Constructor which attach the observer into notifier.
   134       ObserverBase(AlterationNotifier& _notifier) {
   135         attach(_notifier);
   136       }
   137 
   138       /// \brief Constructor which attach the obserever to the same notifier.
   139       ///
   140       /// Constructor which attach the obserever to the same notifier as
   141       /// the other observer is attached to. 
   142       ObserverBase(const ObserverBase& copy) {
   143 	if (copy.attached()) {
   144           attach(*copy.getNotifier());
   145 	}
   146       }
   147 	
   148       /// \brief Destructor
   149       virtual ~ObserverBase() {
   150         if (attached()) {
   151           detach();
   152         }
   153       }
   154 
   155       /// \brief Attaches the observer into an AlterationNotifier.
   156       ///
   157       /// This member attaches the observer into an AlterationNotifier.
   158       ///
   159       void attach(AlterationNotifier& _notifier) {
   160 	notifier = &_notifier;
   161 	notifier->attach(*this);
   162       }
   163 
   164       /// \brief Detaches the observer into an AlterationNotifier.
   165       ///
   166       /// This member detaches the observer from an AlterationNotifier.
   167       ///
   168       void detach() {
   169         notifier->detach(*this);
   170       }
   171 	
   172 
   173       /// \brief Gives back a pointer to the notifier which the map 
   174       /// attached into.
   175       ///
   176       /// This function gives back a pointer to the notifier which the map
   177       /// attached into.
   178       ///
   179       Notifier* getNotifier() const { return const_cast<Notifier*>(notifier); }
   180       
   181       /// Gives back true when the observer is attached into a notifier.
   182       bool attached() const { return notifier != 0; }
   183 
   184     private:
   185 
   186       ObserverBase& operator=(const ObserverBase& copy);
   187 
   188     protected:
   189       
   190       Notifier* notifier;
   191       int notifier_index;
   192 
   193       /// \brief The member function to notificate the observer about an
   194       /// item is added to the container.
   195       ///
   196       /// The add() member function notificates the observer about an item
   197       /// is added to the container. It have to be overrided in the
   198       /// subclasses.
   199 	
   200       virtual void add(const Item&) = 0;
   201 
   202       /// \brief The member function to notificate the observer about 
   203       /// more item is added to the container.
   204       ///
   205       /// The add() member function notificates the observer about more item
   206       /// is added to the container. It have to be overrided in the
   207       /// subclasses.
   208 
   209       virtual void add(const std::vector<Item>& items) {
   210         int i;
   211         try {
   212           for (i = 0; i < (int)items.size(); ++i) {
   213             add(items[i]);
   214           }
   215         } catch (...) {
   216           for (int j = 0; j < i; ++j) {
   217             add(items[j]);
   218           }          
   219           throw;
   220         }
   221       }
   222 
   223       /// \brief The member function to notificate the observer about an
   224       /// item is erased from the container.
   225       ///
   226       /// The erase() member function notificates the observer about an
   227       /// item is erased from the container. It have to be overrided in
   228       /// the subclasses.
   229 	
   230       virtual void erase(const Item&) = 0;
   231 
   232       /// \brief The member function to notificate the observer about 
   233       /// more item is erased from the container.
   234       ///
   235       /// The erase() member function notificates the observer about more item
   236       /// is erased from the container. It have to be overrided in the
   237       /// subclasses.
   238       virtual void erase(const std::vector<Item>& items) {
   239         for (int i = 0; i < (int)items.size(); ++i) {
   240           erase(items[i]);
   241         }
   242       }
   243 
   244       /// \brief The member function to notificate the observer about the
   245       /// container is built.
   246       ///
   247       /// The build() member function notificates the observer about the
   248       /// container is built from an empty container. It have to be
   249       /// overrided in the subclasses.
   250 
   251       virtual void build() {
   252         Item it;
   253         try {
   254           for (notifier->first(it); it != INVALID; notifier->next(it)) {
   255             add(it);
   256           }
   257         } catch (...) {
   258           Item jt;
   259           for (notifier->first(jt); jt != it; notifier->next(jt)) {
   260             erase(jt);
   261           }
   262           throw;
   263         }
   264       }
   265 
   266       /// \brief The member function to notificate the observer about all
   267       /// items are erased from the container.
   268       ///
   269       /// The clear() member function notificates the observer about all
   270       /// items are erased from the container. It have to be overrided in
   271       /// the subclasses.      
   272       virtual void clear() {
   273         Item it;
   274         for (notifier->first(it); it != INVALID; notifier->next(it)) {
   275           erase(it);
   276         }
   277       }
   278 
   279     };
   280 	
   281   protected:
   282 
   283     const Container* container;
   284 
   285     typedef std::vector<ObserverBase*> Observers; 
   286     Observers observers;
   287 
   288 		
   289   public:
   290 
   291     /// \brief Default constructor.
   292     ///
   293     /// The default constructor of the AlterationNotifier. 
   294     /// It creates an empty notifier.
   295     AlterationNotifier() 
   296       : container(0) {}
   297 
   298     /// \brief Constructor.
   299     ///
   300     /// Constructor with the observed container parameter.
   301     AlterationNotifier(const Container& _container) 
   302       : container(&_container) {}
   303 
   304     /// \brief Copy Constructor of the AlterationNotifier. 
   305     ///
   306     /// Copy constructor of the AlterationNotifier. 
   307     /// It creates only an empty notifier because the copiable
   308     /// notifier's observers have to be registered still into that notifier.
   309     AlterationNotifier(const AlterationNotifier& _notifier) 
   310       : container(_notifier.container) {}
   311 
   312     /// \brief Destructor.
   313     ///		
   314     /// Destructor of the AlterationNotifier.
   315     ///
   316     ~AlterationNotifier() {
   317       typename Observers::iterator it;
   318       for (it = observers.begin(); it != observers.end(); ++it) {
   319 	(*it)->notifier = 0;
   320       }
   321     }
   322 
   323     /// \brief Sets the container.
   324     ///
   325     /// Sets the container.
   326     void setContainer(const Container& _container) {
   327       container = &_container;
   328     }
   329 
   330   protected:
   331 
   332     AlterationNotifier& operator=(const AlterationNotifier&);
   333 
   334   public:
   335 
   336 
   337 
   338     /// \brief First item in the container.
   339     ///
   340     /// Returns the first item in the container. It is
   341     /// for start the iteration on the container.
   342     void first(Item& item) const {
   343       container->first(item);
   344     }
   345 
   346     /// \brief Next item in the container.
   347     ///
   348     /// Returns the next item in the container. It is
   349     /// for iterate on the container.
   350     void next(Item& item) const {
   351       container->next(item);
   352     }
   353 
   354     /// \brief Returns the id of the item.
   355     ///
   356     /// Returns the id of the item provided by the container.
   357     int id(const Item& item) const {
   358       return container->id(item);
   359     }
   360 
   361     /// \brief Returns the maximum id of the container.
   362     ///
   363     /// Returns the maximum id of the container.
   364     int maxId() const {
   365       return container->maxId(Item());
   366     }
   367 		
   368   protected:
   369 
   370     void attach(ObserverBase& observer) {
   371       observers.push_back(&observer);
   372       observer.notifier = this;
   373       observer.notifier_index = observers.size() - 1;
   374     } 
   375 
   376     void detach(ObserverBase& observer) {
   377       observers.back()->notifier_index = observer.notifier_index; 
   378       observers[observer.notifier_index] = observers.back();
   379       observers.pop_back();
   380       observer.notifier = 0;
   381     }
   382 
   383   public:
   384 	
   385     /// \brief Notifies all the registed observers about an item added to 
   386     /// the container.
   387     ///
   388     /// It notifies all the registed observers about an item added to 
   389     /// the container.
   390     /// 
   391     void add(const Item& item) {
   392       typename Observers::iterator it;
   393       try {
   394         for (it = observers.begin(); it != observers.end(); ++it) {
   395           (*it)->add(item);
   396         }
   397       } catch (...) {
   398         typename Observers::iterator jt;
   399         for (jt = observers.begin(); jt != it; ++jt) {
   400           (*it)->erase(item);
   401         }
   402         throw;
   403       }
   404     }	
   405 
   406     /// \brief Notifies all the registed observers about more item added to 
   407     /// the container.
   408     ///
   409     /// It notifies all the registed observers about more item added to 
   410     /// the container.
   411     /// 
   412     void add(const std::vector<Item>& items) {
   413       typename Observers::iterator it;
   414       try {
   415         for (it = observers.begin(); it != observers.end(); ++it) {
   416           (*it)->add(items);
   417         }
   418       } catch (...) {
   419         typename Observers::iterator jt;
   420         for (jt = observers.begin(); jt != it; ++jt) {
   421           (*it)->erase(items);
   422         }
   423         throw;
   424       }
   425     }	
   426 
   427     /// \brief Notifies all the registed observers about an item erased from 
   428     /// the container.
   429     ///	
   430     /// It notifies all the registed observers about an item erased from 
   431     /// the container.
   432     /// 
   433     void erase(const Item& key) {
   434       typename Observers::iterator it;
   435       for (it = observers.begin(); it != observers.end(); ++it) {
   436 	(*it)->erase(key);
   437       }
   438     }
   439 
   440     /// \brief Notifies all the registed observers about more item erased  
   441     /// from the container.
   442     ///	
   443     /// It notifies all the registed observers about more item erased from 
   444     /// the container.
   445     /// 
   446     void erase(const std::vector<Item>& items) {
   447       typename Observers::iterator it;
   448       for (it = observers.begin(); it != observers.end(); ++it) {
   449 	(*it)->erase(items);
   450       }
   451     }
   452 
   453     /// \brief Notifies all the registed observers about the container is 
   454     /// built.
   455     ///		
   456     /// Notifies all the registed observers about the container is built
   457     /// from an empty container.
   458     void build() {
   459       typename Observers::iterator it;
   460       try {
   461         for (it = observers.begin(); it != observers.end(); ++it) {
   462           (*it)->build();
   463         }
   464       } catch (...) {
   465         typename Observers::iterator jt;
   466         for (jt = observers.begin(); jt != it; ++jt) {
   467           (*it)->clear();
   468         }
   469         throw;
   470       }
   471     }
   472 
   473 
   474     /// \brief Notifies all the registed observers about all items are 
   475     /// erased.
   476     ///
   477     /// Notifies all the registed observers about all items are erased
   478     /// from the container.
   479     void clear() {
   480       typename Observers::iterator it;
   481       for (it = observers.begin(); it != observers.end(); ++it) {
   482 	(*it)->clear();
   483       }
   484     }
   485   };
   486 
   487 }
   488 
   489 #endif