lemon/bits/alteration_notifier.h
author deba
Mon, 03 Oct 2005 13:51:25 +0000
changeset 1701 77bb84387815
parent 1685 5b37a10234bc
child 1718 6a958ab38386
permissions -rw-r--r--
Bugfix
     1 /* -*- C++ -*-
     2  * lemon/notifier.h - Part of LEMON, a generic C++ optimization library
     3  *
     4  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     5  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     6  *
     7  * Permission to use, modify and distribute this software is granted
     8  * provided that this copyright notice appears in all copies. For
     9  * precise terms see the accompanying LICENSE file.
    10  *
    11  * This software is provided "AS IS" with no warranty of any kind,
    12  * express or implied, and with no claim as to its suitability for any
    13  * purpose.
    14  *
    15  */
    16 
    17 #ifndef LEMON_ALTERATION_OBSERVER_REGISTRY_H
    18 #define LEMON_ALTERATION_OBSERVER_REGISTRY_H
    19 
    20 #include <vector>
    21 #include <algorithm>
    22 
    23 ///\ingroup graphmapfactory
    24 ///\file
    25 ///\brief Observer registry for graph alteration observers.
    26 
    27 namespace lemon {
    28 
    29   /// \addtogroup graphmapfactory
    30   /// @{
    31 
    32   /// \brief Registry class to register objects observes alterations in 
    33   /// the graph.
    34   ///
    35   /// This class is a registry for the objects which observe the
    36   /// alterations in a container. The alteration observers can be attached
    37   /// to and detached from the registry. The observers have to inherit
    38   /// from the \ref AlterationNotifier::ObserverBase and override
    39   /// the virtual functions in that.
    40   ///
    41   /// The most important application of the alteration observing is the
    42   /// dynamic map implementation.
    43   ///
    44   /// \param _Item The item type what the observers are observing, usually
    45   /// edge or node.
    46   ///
    47   /// \author Balazs Dezso
    48 
    49   template <typename _Item>
    50   class AlterationNotifier {
    51   public:
    52     typedef _Item Item;
    53 
    54     /// ObserverBase is the base class for the observers.
    55 	
    56     /// ObserverBase is the abstract base class for the observers.
    57     /// It will be notified about an item was inserted into or
    58     /// erased from the graph.
    59     ///
    60     /// The observer interface contains some pure virtual functions
    61     /// to override. The add() and erase() functions are
    62     /// to notify the oberver when one item is added or
    63     /// erased.
    64     ///
    65     /// The build() and clear() members are to notify the observer
    66     /// about the container is built from an empty container or
    67     /// is cleared to an empty container. 
    68     /// 
    69     /// \author Balazs Dezso
    70 
    71     class ObserverBase {
    72     protected:
    73       typedef AlterationNotifier Registry;
    74 
    75       friend class AlterationNotifier;
    76 
    77       /// \brief Default constructor.
    78       ///
    79       /// Default constructor for ObserverBase.
    80       /// 
    81       ObserverBase() : registry(0) {}
    82 
    83       ObserverBase(const ObserverBase& copy) {
    84 	if (copy.attached()) {
    85 	  copy.getRegistry()->attach(*this);
    86 	}
    87       }
    88 	
    89       virtual ~ObserverBase() {}
    90 
    91       /// \brief Attaches the observer into an AlterationNotifier.
    92       ///
    93       /// This member attaches the observer into an AlterationNotifier.
    94       ///
    95       void attach(AlterationNotifier& r) {
    96 	registry = &r;
    97 	registry->attach(*this);
    98       }
    99 
   100       /// \brief Detaches the observer into an AlterationNotifier.
   101       ///
   102       /// This member detaches the observer from an AlterationNotifier.
   103       ///
   104       void detach() {
   105 	if (registry) {
   106 	  registry->detach(*this);
   107 	}
   108       }
   109 	
   110 
   111       /// Gives back a pointer to the registry what the map attached into.
   112 
   113       /// This function gives back a pointer to the registry what the map
   114       /// attached into.
   115       ///
   116       Registry* getRegistry() const { return const_cast<Registry*>(registry); }
   117       
   118       /// Gives back true when the observer is attached into a registry.
   119       bool attached() const { return registry != 0; }
   120 
   121     private:
   122 
   123       ObserverBase& operator=(const ObserverBase& copy);
   124 
   125     protected:
   126       
   127       Registry* registry;
   128       int registry_index;
   129 
   130     public:
   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       /// simulitem is added to the container.
   143       ///
   144       /// The add() member function notificates the observer about an 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       virtual void erase(const std::vector<Item>& items) {
   164 	for (int i = 0; i < (int)items.size(); ++i) {
   165 	  erase(items[i]);
   166 	}
   167       }
   168 
   169       /// \brief The member function to notificate the observer about the
   170       /// container is built.
   171       ///
   172       /// The build() member function notificates the observer about the
   173       /// container is built from an empty container. It have to be
   174       /// overrided in the subclasses.
   175 
   176       virtual void build() = 0;
   177 
   178       /// \brief The member function to notificate the observer about all
   179       /// items are erased from the container.
   180       ///
   181       /// The clear() member function notificates the observer about all
   182       /// items are erased from the container. It have to be overrided in
   183       /// the subclasses.
   184       
   185       virtual void clear() = 0;
   186 
   187     };
   188 	
   189   protected:
   190 	
   191 
   192     typedef std::vector<ObserverBase*> Container; 
   193 
   194     Container container;
   195 
   196 		
   197   public:
   198 
   199     /// Default constructor.
   200 	
   201     ///
   202     /// The default constructor of the AlterationNotifier. 
   203     /// It creates an empty registry.
   204     AlterationNotifier() {}
   205 
   206     /// Copy Constructor of the AlterationNotifier. 
   207 	
   208     /// Copy constructor of the AlterationNotifier. 
   209     /// It creates only an empty registry because the copiable
   210     /// registry's observers have to be registered still into that registry.
   211     AlterationNotifier(const AlterationNotifier&) {}
   212 
   213     /// Assign operator.
   214 		
   215     /// Assign operator for the AlterationNotifier. 
   216     /// It makes the notifier only empty because the copiable
   217     /// notifier's observers have to be registered still into that registry.
   218     AlterationNotifier& operator=(const AlterationNotifier&) {
   219       typename Container::iterator it;
   220       for (it = container.begin(); it != container.end(); ++it) {
   221 	(*it)->registry = 0;
   222       }
   223     }
   224 
   225     /// Destructor.
   226 				
   227     /// Destructor of the AlterationNotifier.
   228     ///
   229     ~AlterationNotifier() {
   230       typename Container::iterator it;
   231       for (it = container.begin(); it != container.end(); ++it) {
   232 	(*it)->registry = 0;
   233       }
   234     }
   235 	
   236 	
   237   protected:
   238 
   239     void attach(ObserverBase& observer) {
   240       container.push_back(&observer);
   241       observer.registry = this;
   242       observer.registry_index = container.size()-1;
   243     } 
   244 
   245     void detach(ObserverBase& base) {
   246       container.back()->registry_index = base.registry_index; 
   247       container[base.registry_index] = container.back();
   248       container.pop_back();
   249       base.registry = 0;
   250     }
   251 
   252   public:
   253 	
   254     /// \brief Notifies all the registered observers about an Item added to 
   255     /// the container.
   256     ///
   257     /// It notifies all the registered observers about an Item added to 
   258     /// the container.
   259     /// 
   260     void add(const Item& item) {
   261       typename Container::iterator it;
   262       for (it = container.begin(); it != container.end(); ++it) {
   263 	(*it)->add(item);
   264       }
   265     }	
   266 
   267     /// \brief Notifies all the registered observers about more Item added to 
   268     /// the container.
   269     ///
   270     /// It notifies all the registered observers about more Item added to 
   271     /// the container.
   272     /// 
   273     void add(const std::vector<Item>& items) {
   274       typename Container::iterator it;
   275       for (it = container.begin(); it != container.end(); ++it) {
   276 	(*it)->add(items);
   277       }
   278     }	
   279 
   280     /// \brief Notifies all the registered observers about an Item erased from 
   281     /// the container.
   282     ///	
   283     /// It notifies all the registered observers about an Item erased from 
   284     /// the container.
   285     /// 
   286     void erase(const Item& key) {
   287       typename Container::iterator it;
   288       for (it = container.begin(); it != container.end(); ++it) {
   289 	(*it)->erase(key);
   290       }
   291     }
   292 
   293     /// \brief Notifies all the registered observers about more Item erased  
   294     /// from the container.
   295     ///	
   296     /// It notifies all the registered observers about more Item erased from 
   297     /// the container.
   298     /// 
   299     void erase(const std::vector<Item>& items) {
   300       typename Container::iterator it;
   301       for (it = container.begin(); it != container.end(); ++it) {
   302 	(*it)->erase(items);
   303       }
   304     }
   305     
   306 
   307     /// \brief Notifies all the registered observers about the container is 
   308     /// built.
   309     ///		
   310     /// Notifies all the registered observers about the container is built
   311     /// from an empty container.
   312     void build() {
   313       typename Container::iterator it;
   314       for (it = container.begin(); it != container.end(); ++it) {
   315 	(*it)->build();
   316       }
   317     }
   318 
   319 
   320     /// \brief Notifies all the registered observers about all Items are 
   321     /// erased.
   322     ///
   323     /// Notifies all the registered observers about all Items are erased
   324     /// from the container.
   325     void clear() {
   326       typename Container::iterator it;
   327       for (it = container.begin(); it != container.end(); ++it) {
   328 	(*it)->clear();
   329       }
   330     }
   331   };
   332 
   333 
   334   /// \brief Class to extend a graph with the functionality of alteration
   335   /// observing.
   336   ///
   337   /// AlterableGraphExtender extends the _Base graphs functionality with
   338   /// the possibility of alteration observing. It defines two observer
   339   /// registrys for the nodes and mapes.
   340   /// 
   341   /// \todo Document what "alteration observing" is. And probably find a
   342   /// better (shorter) name.
   343   ///
   344   /// \param _Base is the base class to extend.
   345   ///
   346   /// \pre _Base is conform to the BaseGraphComponent concept.
   347   ///
   348   /// \post AlterableGraphExtender<_Base> is conform to the
   349   /// AlterableGraphComponent concept.
   350   ///
   351   /// \author Balazs Dezso
   352 
   353   template <typename _Base> 
   354   class AlterableGraphExtender : public _Base {
   355   public:
   356 
   357     typedef AlterableGraphExtender Graph;
   358     typedef _Base Parent;
   359 
   360     typedef typename Parent::Node Node;
   361     typedef typename Parent::Edge Edge;
   362 
   363     /// The edge observer registry.
   364     typedef AlterationNotifier<Edge> EdgeNotifier;
   365     /// The node observer registry.
   366     typedef AlterationNotifier<Node> NodeNotifier;
   367 
   368 
   369   protected:
   370 
   371     mutable EdgeNotifier edge_notifier;
   372 
   373     mutable NodeNotifier node_notifier;
   374 
   375   public:
   376 
   377     /// \brief Gives back the edge alteration notifier.
   378     ///
   379     /// Gives back the edge alteration notifier.
   380     EdgeNotifier& getNotifier(Edge) const {
   381       return edge_notifier;
   382     }
   383 
   384     /// \brief Gives back the node alteration notifier.
   385     ///
   386     /// Gives back the node alteration notifier.
   387     NodeNotifier& getNotifier(Node) const {
   388       return node_notifier;
   389     }
   390 
   391     ~AlterableGraphExtender() {
   392       node_notifier.clear();
   393       edge_notifier.clear();
   394     }
   395     
   396   };
   397 
   398   /// \brief Class to extend an undirected graph with the functionality of
   399   /// alteration observing.
   400   ///
   401   /// \todo Document.
   402   ///
   403   /// \sa AlterableGraphExtender
   404   ///
   405   /// \bug This should be done some other way. Possibilities: template
   406   /// specialization (not very easy, if at all possible); some kind of
   407   /// enable_if boost technique?
   408 
   409   template <typename _Base> 
   410   class AlterableUndirGraphExtender
   411     : public AlterableGraphExtender<_Base> {
   412   public:
   413 
   414     typedef AlterableUndirGraphExtender Graph;
   415     typedef AlterableGraphExtender<_Base> Parent;
   416 
   417     typedef typename Parent::UndirEdge UndirEdge;
   418 
   419     /// The edge observer registry.
   420     typedef AlterationNotifier<UndirEdge> UndirEdgeNotifier;
   421 
   422   protected:
   423 
   424     mutable UndirEdgeNotifier undir_edge_notifier;
   425 
   426   public:
   427 
   428     using Parent::getNotifier;
   429     UndirEdgeNotifier& getNotifier(UndirEdge) const {
   430       return undir_edge_notifier;
   431     }
   432 
   433     ~AlterableUndirGraphExtender() {
   434       undir_edge_notifier.clear();
   435     }
   436   };
   437   
   438 /// @}
   439   
   440 
   441 }
   442 
   443 #endif