lemon/bits/alteration_notifier.h
author deba
Wed, 01 Mar 2006 10:25:30 +0000
changeset 1991 d7442141d9ef
parent 1979 c2992fd74dad
child 1996 5dc13b93f8b4
permissions -rw-r--r--
The graph adadptors can be alteration observed.
In most cases it uses the adapted graph alteration notifiers.
Only special case is now the UndirGraphAdaptor, where
we have to proxy the signals from the graph.

The SubBidirGraphAdaptor is removed, because it doest not
gives more feature than the EdgeSubGraphAdaptor<UndirGraphAdaptor<Graph>>.

The ResGraphAdaptor is based on this composition.
     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