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