lemon/bits/alteration_notifier.h
author deba
Thu, 02 Mar 2006 14:22:03 +0000
changeset 1995 c1fc2c14a3ae
parent 1979 c2992fd74dad
child 1996 5dc13b93f8b4
permissions -rw-r--r--
Bugfix in bpugraph
     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_ALTERATION_NOTIFIER_H
    20 #define LEMON_ALTERATION_NOTIFIER_H
    21 
    22 #include <vector>
    23 #include <algorithm>
    24 
    25 ///\ingroup graphmapfactory
    26 ///\file
    27 ///\brief Observer registry for graph alteration observers.
    28 
    29 namespace lemon {
    30 
    31   /// \addtogroup graphmapfactory
    32   /// @{
    33 
    34   /// \brief Registry class to register objects observes alterations in 
    35   /// the graph.
    36   ///
    37   /// This class is a registry for the objects which observe the
    38   /// alterations in a container. The alteration observers can be attached
    39   /// to and detached from the registry. The observers have to inherit
    40   /// from the \ref AlterationNotifier::ObserverBase and override
    41   /// the virtual functions in that.
    42   ///
    43   /// The most important application of the alteration observing is the
    44   /// dynamic map implementation.
    45   ///
    46   /// \param _Item The item type what the observers are observing, usually
    47   /// edge or node.
    48   ///
    49   /// \author Balazs Dezso
    50 
    51   template <typename _Item>
    52   class AlterationNotifier {
    53   public:
    54 
    55     typedef True Notifier;
    56 
    57     typedef _Item Item;
    58 
    59     /// ObserverBase is the base class for the observers.
    60 	
    61     /// ObserverBase is the abstract base class for the observers.
    62     /// It will be notified about an item was inserted into or
    63     /// erased from the graph.
    64     ///
    65     /// The observer interface contains some pure virtual functions
    66     /// to override. The add() and erase() functions are
    67     /// to notify the oberver when one item is added or
    68     /// erased.
    69     ///
    70     /// The build() and clear() members are to notify the observer
    71     /// about the container is built from an empty container or
    72     /// is cleared to an empty container. 
    73     /// 
    74     /// \author Balazs Dezso
    75 
    76     class ObserverBase {
    77     protected:
    78       typedef AlterationNotifier Registry;
    79 
    80       friend class AlterationNotifier;
    81 
    82       /// \brief Default constructor.
    83       ///
    84       /// Default constructor for ObserverBase.
    85       /// 
    86       ObserverBase() : registry(0) {}
    87 
    88       ObserverBase(const ObserverBase& copy) {
    89 	if (copy.attached()) {
    90 	  copy.getRegistry()->attach(*this);
    91 	}
    92       }
    93 	
    94       virtual ~ObserverBase() {}
    95 
    96       /// \brief Attaches the observer into an AlterationNotifier.
    97       ///
    98       /// This member attaches the observer into an AlterationNotifier.
    99       ///
   100       void attach(AlterationNotifier& r) {
   101 	registry = &r;
   102 	registry->attach(*this);
   103       }
   104 
   105       /// \brief Detaches the observer into an AlterationNotifier.
   106       ///
   107       /// This member detaches the observer from an AlterationNotifier.
   108       ///
   109       void detach() {
   110 	if (registry) {
   111 	  registry->detach(*this);
   112 	}
   113       }
   114 	
   115 
   116       /// Gives back a pointer to the registry what the map attached into.
   117 
   118       /// This function gives back a pointer to the registry what the map
   119       /// attached into.
   120       ///
   121       Registry* getRegistry() const { return const_cast<Registry*>(registry); }
   122       
   123       /// Gives back true when the observer is attached into a registry.
   124       bool attached() const { return registry != 0; }
   125 
   126     private:
   127 
   128       ObserverBase& operator=(const ObserverBase& copy);
   129 
   130     protected:
   131       
   132       Registry* registry;
   133       int registry_index;
   134 
   135       /// \brief The member function to notificate the observer about an
   136       /// item is added to the container.
   137       ///
   138       /// The add() member function notificates the observer about an item
   139       /// is added to the container. It have to be overrided in the
   140       /// subclasses.
   141 	
   142       virtual void add(const Item&) = 0;
   143 
   144       /// \brief The member function to notificate the observer about 
   145       /// more item is added to the container.
   146       ///
   147       /// The add() member function notificates the observer about more item
   148       /// is added to the container. It have to be overrided in the
   149       /// subclasses.
   150 
   151       virtual void add(const std::vector<Item>& items) {
   152 	for (int i = 0; i < (int)items.size(); ++i) {
   153 	  add(items[i]);
   154 	}
   155       }
   156 
   157       /// \brief The member function to notificate the observer about an
   158       /// item is erased from the container.
   159       ///
   160       /// The erase() member function notificates the observer about an
   161       /// item is erased from the container. It have to be overrided in
   162       /// the subclasses.
   163 	
   164       virtual void erase(const Item&) = 0;
   165 
   166       /// \brief The member function to notificate the observer about 
   167       /// more item is erased from the container.
   168       ///
   169       /// The erase() member function notificates the observer about more item
   170       /// is erased from the container. It have to be overrided in the
   171       /// subclasses.
   172       virtual void erase(const std::vector<Item>& items) {
   173 	for (int i = 0; i < (int)items.size(); ++i) {
   174 	  erase(items[i]);
   175 	}
   176       }
   177 
   178       /// \brief The member function to notificate the observer about the
   179       /// container is built.
   180       ///
   181       /// The build() member function notificates the observer about the
   182       /// container is built from an empty container. It have to be
   183       /// overrided in the subclasses.
   184 
   185       virtual void build() = 0;
   186 
   187       /// \brief The member function to notificate the observer about all
   188       /// items are erased from the container.
   189       ///
   190       /// The clear() member function notificates the observer about all
   191       /// items are erased from the container. It have to be overrided in
   192       /// the subclasses.
   193       
   194       virtual void clear() = 0;
   195 
   196     };
   197 	
   198   protected:
   199 	
   200 
   201     typedef std::vector<ObserverBase*> Container; 
   202 
   203     Container container;
   204 
   205 		
   206   public:
   207 
   208     /// Default constructor.
   209 	
   210     ///
   211     /// The default constructor of the AlterationNotifier. 
   212     /// It creates an empty registry.
   213     AlterationNotifier() {}
   214 
   215     /// Copy Constructor of the AlterationNotifier. 
   216 	
   217     /// Copy constructor of the AlterationNotifier. 
   218     /// It creates only an empty registry because the copiable
   219     /// registry's observers have to be registered still into that registry.
   220     AlterationNotifier(const AlterationNotifier&) {}
   221 
   222     /// Assign operator.
   223 		
   224     /// Assign operator for the AlterationNotifier. 
   225     /// It makes the notifier only empty because the copiable
   226     /// notifier's observers have to be registered still into that registry.
   227     AlterationNotifier& operator=(const AlterationNotifier&) {
   228       typename Container::iterator it;
   229       for (it = container.begin(); it != container.end(); ++it) {
   230 	(*it)->registry = 0;
   231       }
   232     }
   233 
   234     /// Destructor.
   235 				
   236     /// Destructor of the AlterationNotifier.
   237     ///
   238     ~AlterationNotifier() {
   239       typename Container::iterator it;
   240       for (it = container.begin(); it != container.end(); ++it) {
   241 	(*it)->registry = 0;
   242       }
   243     }
   244 	
   245 	
   246   protected:
   247 
   248     void attach(ObserverBase& observer) {
   249       container.push_back(&observer);
   250       observer.registry = this;
   251       observer.registry_index = container.size()-1;
   252     } 
   253 
   254     void detach(ObserverBase& base) {
   255       container.back()->registry_index = base.registry_index; 
   256       container[base.registry_index] = container.back();
   257       container.pop_back();
   258       base.registry = 0;
   259     }
   260 
   261   public:
   262 	
   263     /// \brief Notifies all the registered observers about an Item added to 
   264     /// the container.
   265     ///
   266     /// It notifies all the registered observers about an Item added to 
   267     /// the container.
   268     /// 
   269     void add(const Item& item) {
   270       typename Container::iterator it;
   271       try {
   272         for (it = container.begin(); it != container.end(); ++it) {
   273           (*it)->add(item);
   274         }
   275       } catch (...) {
   276         typename Container::iterator jt;
   277         for (jt = container.begin(); jt != it; ++it) {
   278           (*it)->erase(item);
   279         }
   280         throw;
   281       }
   282     }	
   283 
   284     /// \brief Notifies all the registered observers about more Item added to 
   285     /// the container.
   286     ///
   287     /// It notifies all the registered observers about more Item added to 
   288     /// the container.
   289     /// 
   290     void add(const std::vector<Item>& items) {
   291       typename Container::iterator it;
   292       try {
   293         for (it = container.begin(); it != container.end(); ++it) {
   294           (*it)->add(items);
   295         }
   296       } catch (...) {
   297         typename Container::iterator jt;
   298         for (jt = container.begin(); jt != it; ++it) {
   299           (*it)->erase(items);
   300         }
   301         throw;
   302       }
   303     }	
   304 
   305     /// \brief Notifies all the registered observers about an Item erased from 
   306     /// the container.
   307     ///	
   308     /// It notifies all the registered observers about an Item erased from 
   309     /// the container.
   310     /// 
   311     void erase(const Item& key) {
   312       typename Container::iterator it;
   313       for (it = container.begin(); it != container.end(); ++it) {
   314 	(*it)->erase(key);
   315       }
   316     }
   317 
   318     /// \brief Notifies all the registered observers about more Item erased  
   319     /// from the container.
   320     ///	
   321     /// It notifies all the registered observers about more Item erased from 
   322     /// the container.
   323     /// 
   324     void erase(const std::vector<Item>& items) {
   325       typename Container::iterator it;
   326       for (it = container.begin(); it != container.end(); ++it) {
   327 	(*it)->erase(items);
   328       }
   329     }
   330 
   331     /// \brief Notifies all the registered observers about the container is 
   332     /// built.
   333     ///		
   334     /// Notifies all the registered observers about the container is built
   335     /// from an empty container.
   336     void build() {
   337       typename Container::iterator it;
   338       try {
   339         for (it = container.begin(); it != container.end(); ++it) {
   340           (*it)->build();
   341         }
   342       } catch (...) {
   343         typename Container::iterator jt;
   344         for (jt = container.begin(); jt != it; ++it) {
   345           (*it)->clear();
   346         }
   347         throw;
   348       }
   349     }
   350 
   351 
   352     /// \brief Notifies all the registered observers about all Items are 
   353     /// erased.
   354     ///
   355     /// Notifies all the registered observers about all Items are erased
   356     /// from the container.
   357     void clear() {
   358       typename Container::iterator it;
   359       for (it = container.begin(); it != container.end(); ++it) {
   360 	(*it)->clear();
   361       }
   362     }
   363   };
   364 
   365   
   366 /// @}
   367   
   368 
   369 }
   370 
   371 #endif