lemon/bits/alteration_notifier.h
author ladanyi
Fri, 29 Jul 2005 12:30:28 +0000
changeset 1607 da99ef6dff78
parent 1435 8e85e6bbefdf
child 1685 5b37a10234bc
permissions -rw-r--r--
small fix
     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       virtual ~ObserverBase() {}
    84 
    85       /// \brief Attaches the observer into an AlterationNotifier.
    86       ///
    87       /// This member attaches the observer into an AlterationNotifier.
    88       ///
    89       void attach(AlterationNotifier& r) {
    90 	registry = &r;
    91 	registry->attach(*this);
    92       }
    93 
    94       /// \brief Detaches the observer into an AlterationNotifier.
    95       ///
    96       /// This member detaches the observer from an AlterationNotifier.
    97       ///
    98       void detach() {
    99 	if (registry) {
   100 	  registry->detach(*this);
   101 	}
   102       }
   103 	
   104 
   105       /// Gives back a pointer to the registry what the map attached into.
   106 
   107       /// This function gives back a pointer to the registry what the map
   108       /// attached into.
   109       ///
   110       Registry* getRegistry() const { return const_cast<Registry*>(registry); }
   111       
   112       /// Gives back true when the observer is attached into a registry.
   113       bool attached() const { return registry != 0; }
   114 	
   115     private:
   116 
   117       ObserverBase(const ObserverBase& copy);
   118       ObserverBase& operator=(const ObserverBase& copy);
   119 
   120     protected:
   121       
   122       Registry* registry;
   123       int registry_index;
   124 
   125     public:
   126 
   127       /// \brief The member function to notificate the observer about an
   128       /// item is added to the container.
   129       ///
   130       /// The add() member function notificates the observer about an item
   131       /// is added to the container. It have to be overrided in the
   132       /// subclasses.
   133 	
   134       virtual void add(const Item&) = 0;
   135 
   136       /// \brief The member function to notificate the observer about 
   137       /// simulitem is added to the container.
   138       ///
   139       /// The add() member function notificates the observer about an item
   140       /// is added to the container. It have to be overrided in the
   141       /// subclasses.
   142 
   143       virtual void add(const std::vector<Item>& items) {
   144 	for (int i = 0; i < (int)items.size(); ++i) {
   145 	  add(items[i]);
   146 	}
   147       }
   148 
   149       /// \brief The member function to notificate the observer about an
   150       /// item is erased from the container.
   151       ///
   152       /// The erase() member function notificates the observer about an
   153       /// item is erased from the container. It have to be overrided in
   154       /// the subclasses.
   155 	
   156       virtual void erase(const Item&) = 0;
   157 
   158       virtual void erase(const std::vector<Item>& items) {
   159 	for (int i = 0; i < (int)items.size(); ++i) {
   160 	  add(items[i]);
   161 	}
   162       }
   163 
   164       /// \brief The member function to notificate the observer about the
   165       /// container is built.
   166       ///
   167       /// The build() member function notificates the observer about the
   168       /// container is built from an empty container. It have to be
   169       /// overrided in the subclasses.
   170 
   171       virtual void build() = 0;
   172 
   173       /// \brief The member function to notificate the observer about all
   174       /// items are erased from the container.
   175       ///
   176       /// The clear() member function notificates the observer about all
   177       /// items are erased from the container. It have to be overrided in
   178       /// the subclasses.
   179       
   180       virtual void clear() = 0;
   181 
   182     };
   183 	
   184   protected:
   185 	
   186 
   187     typedef std::vector<ObserverBase*> Container; 
   188 
   189     Container container;
   190 
   191 		
   192   public:
   193 
   194     /// Default constructor.
   195 	
   196     ///
   197     /// The default constructor of the AlterationNotifier. 
   198     /// It creates an empty registry.
   199     AlterationNotifier() {}
   200 
   201     /// Copy Constructor of the AlterationNotifier. 
   202 	
   203     /// Copy constructor of the AlterationNotifier. 
   204     /// It creates only an empty registry because the copiable
   205     /// registry's observers have to be registered still into that registry.
   206     AlterationNotifier(const AlterationNotifier&) {}
   207 
   208     /// Assign operator.
   209 		
   210     /// Assign operator for the AlterationNotifier. 
   211     /// It makes the notifier only empty because the copiable
   212     /// notifier's observers have to be registered still into that registry.
   213     AlterationNotifier& operator=(const AlterationNotifier&) {
   214       typename Container::iterator it;
   215       for (it = container.begin(); it != container.end(); ++it) {
   216 	(*it)->registry = 0;
   217       }
   218     }
   219 
   220     /// Destructor.
   221 				
   222     /// Destructor of the AlterationNotifier.
   223     ///
   224     ~AlterationNotifier() {
   225       typename Container::iterator it;
   226       for (it = container.begin(); it != container.end(); ++it) {
   227 	(*it)->registry = 0;
   228       }
   229     }
   230 	
   231 	
   232   protected:
   233 
   234     void attach(ObserverBase& observer) {
   235       container.push_back(&observer);
   236       observer.registry = this;
   237       observer.registry_index = container.size()-1;
   238     } 
   239 
   240     void detach(ObserverBase& base) {
   241       container.back()->registry_index = base.registry_index; 
   242       container[base.registry_index] = container.back();
   243       container.pop_back();
   244       base.registry = 0;
   245     }
   246 
   247   public:
   248 	
   249     /// \brief Notifies all the registered observers about an Item added to 
   250     /// the container.
   251     ///
   252     /// It notifies all the registered observers about an Item added to 
   253     /// the container.
   254     /// 
   255     void add(const Item& item) {
   256       typename Container::iterator it;
   257       for (it = container.begin(); it != container.end(); ++it) {
   258 	(*it)->add(item);
   259       }
   260     }	
   261 
   262     /// \brief Notifies all the registered observers about more Item added to 
   263     /// the container.
   264     ///
   265     /// It notifies all the registered observers about more Item added to 
   266     /// the container.
   267     /// 
   268     void add(const std::vector<Item>& items) {
   269       typename Container::iterator it;
   270       for (it = container.begin(); it != container.end(); ++it) {
   271 	(*it)->add(items);
   272       }
   273     }	
   274 
   275     /// \brief Notifies all the registered observers about an Item erased from 
   276     /// the container.
   277     ///	
   278     /// It notifies all the registered observers about an Item erased from 
   279     /// the container.
   280     /// 
   281     void erase(const Item& key) {
   282       typename Container::iterator it;
   283       for (it = container.begin(); it != container.end(); ++it) {
   284 	(*it)->erase(key);
   285       }
   286     }
   287 
   288     /// \brief Notifies all the registered observers about more Item erased  
   289     /// from the container.
   290     ///	
   291     /// It notifies all the registered observers about more Item erased from 
   292     /// the container.
   293     /// 
   294     void erase(const std::vector<Item>& items) {
   295       typename Container::iterator it;
   296       for (it = container.begin(); it != container.end(); ++it) {
   297 	(*it)->erase(items);
   298       }
   299     }
   300     
   301 
   302     /// \brief Notifies all the registered observers about the container is 
   303     /// built.
   304     ///		
   305     /// Notifies all the registered observers about the container is built
   306     /// from an empty container.
   307     void build() {
   308       typename Container::iterator it;
   309       for (it = container.begin(); it != container.end(); ++it) {
   310 	(*it)->build();
   311       }
   312     }
   313 
   314 
   315     /// \brief Notifies all the registered observers about all Items are 
   316     /// erased.
   317     ///
   318     /// Notifies all the registered observers about all Items are erased
   319     /// from the container.
   320     void clear() {
   321       typename Container::iterator it;
   322       for (it = container.begin(); it != container.end(); ++it) {
   323 	(*it)->clear();
   324       }
   325     }
   326   };
   327 
   328 
   329   /// \brief Class to extend a graph with the functionality of alteration
   330   /// observing.
   331   ///
   332   /// AlterableGraphExtender extends the _Base graphs functionality with
   333   /// the possibility of alteration observing. It defines two observer
   334   /// registrys for the nodes and mapes.
   335   /// 
   336   /// \todo Document what "alteration observing" is. And probably find a
   337   /// better (shorter) name.
   338   ///
   339   /// \param _Base is the base class to extend.
   340   ///
   341   /// \pre _Base is conform to the BaseGraphComponent concept.
   342   ///
   343   /// \post AlterableGraphExtender<_Base> is conform to the
   344   /// AlterableGraphComponent concept.
   345   ///
   346   /// \author Balazs Dezso
   347 
   348   template <typename _Base> 
   349   class AlterableGraphExtender : public _Base {
   350   public:
   351 
   352     typedef AlterableGraphExtender Graph;
   353     typedef _Base Parent;
   354 
   355     typedef typename Parent::Node Node;
   356     typedef typename Parent::Edge Edge;
   357 
   358     /// The edge observer registry.
   359     typedef AlterationNotifier<Edge> EdgeNotifier;
   360     /// The node observer registry.
   361     typedef AlterationNotifier<Node> NodeNotifier;
   362 
   363 
   364   protected:
   365 
   366     mutable EdgeNotifier edge_notifier;
   367 
   368     mutable NodeNotifier node_notifier;
   369 
   370   public:
   371 
   372     /// \brief Gives back the edge alteration notifier.
   373     ///
   374     /// Gives back the edge alteration notifier.
   375     EdgeNotifier& getNotifier(Edge) const {
   376       return edge_notifier;
   377     }
   378 
   379     /// \brief Gives back the node alteration notifier.
   380     ///
   381     /// Gives back the node alteration notifier.
   382     NodeNotifier& getNotifier(Node) const {
   383       return node_notifier;
   384     }
   385 
   386     ~AlterableGraphExtender() {
   387       node_notifier.clear();
   388       edge_notifier.clear();
   389     }
   390     
   391   };
   392 
   393   /// \brief Class to extend an undirected graph with the functionality of
   394   /// alteration observing.
   395   ///
   396   /// \todo Document.
   397   ///
   398   /// \sa AlterableGraphExtender
   399   ///
   400   /// \bug This should be done some other way. Possibilities: template
   401   /// specialization (not very easy, if at all possible); some kind of
   402   /// enable_if boost technique?
   403 
   404   template <typename _Base> 
   405   class AlterableUndirGraphExtender
   406     : public AlterableGraphExtender<_Base> {
   407   public:
   408 
   409     typedef AlterableUndirGraphExtender Graph;
   410     typedef AlterableGraphExtender<_Base> Parent;
   411 
   412     typedef typename Parent::UndirEdge UndirEdge;
   413 
   414     /// The edge observer registry.
   415     typedef AlterationNotifier<UndirEdge> UndirEdgeNotifier;
   416 
   417   protected:
   418 
   419     mutable UndirEdgeNotifier undir_edge_notifier;
   420 
   421   public:
   422 
   423     using Parent::getNotifier;
   424     UndirEdgeNotifier& getNotifier(UndirEdge) const {
   425       return undir_edge_notifier;
   426     }
   427 
   428     ~AlterableUndirGraphExtender() {
   429       undir_edge_notifier.clear();
   430     }
   431   };
   432   
   433 /// @}
   434   
   435 
   436 }
   437 
   438 #endif