src/lemon/alteration_notifier.h
author deba
Fri, 04 Mar 2005 17:20:11 +0000
changeset 1194 7bce0ef61d6b
parent 1134 56b07afdbf8d
child 1204 c3e29c6ae4e4
permissions -rw-r--r--
Change test to be up to date.
Deprecated test, it should be used rather the heap_test.cc and heap_test.h.
     1 /* -*- C++ -*-
     2  * src/lemon/notifier.h - Part of LEMON, a generic C++ optimization library
     3  *
     4  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     5  * (Egervary Combinatorial Optimization Research Group, 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 graphmaps
    24 ///\file
    25 ///\brief Observer registry for graph alteration observers.
    26 
    27 using namespace std;
    28 
    29 namespace lemon {
    30 
    31   /// \addtogroup graphmaps
    32   /// @{
    33 
    34   /// Registry class to register objects observes alterations in the graph.
    35 
    36   /// This class is a registry for the objects which observe the
    37   /// alterations in a container. The alteration observers can be attached
    38   /// to and detached from the registry. The observers have to inherit
    39   /// from the \ref AlterationNotifier::ObserverBase and override
    40   /// the virtual functions in that.
    41   ///
    42   /// The most important application of the alteration observing is the
    43   /// dynamic map implementation when the observers are observing the
    44   /// alterations in the graph.
    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 builded 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       /// Default constructor.
    80 
    81       /// Default constructor for ObserverBase.
    82       /// 
    83       ObserverBase() : registry(0) {}
    84 
    85       virtual ~ObserverBase() {}
    86 
    87       /// Attaches the observer into an AlterationNotifier.
    88 
    89       /// This member attaches the observer into an AlterationNotifier.
    90       ///
    91       void attach(AlterationNotifier& r) {
    92 	registry = &r;
    93 	registry->attach(*this);
    94       }
    95 
    96       /// Detaches the observer into an AlterationNotifier.
    97 
    98       /// This member detaches the observer from an AlterationNotifier.
    99       ///
   100       void detach() {
   101 	if (registry) {
   102 	  registry->detach(*this);
   103 	}
   104       }
   105 	
   106 
   107       /// Gives back a pointer to the registry what the map attached into.
   108 
   109       /// This function gives back a pointer to the registry what the map
   110       /// attached into.
   111       ///
   112       Registry* getRegistry() const { return const_cast<Registry*>(registry); }
   113       
   114       /// Gives back true when the observer is attached into a registry.
   115       bool attached() const { return registry != 0; }
   116 	
   117     private:
   118 
   119       ObserverBase(const ObserverBase& copy);
   120       ObserverBase& operator=(const ObserverBase& copy);
   121 
   122     protected:
   123       
   124       Registry* registry;
   125       int registry_index;
   126 
   127     public:
   128 
   129       /// \brief The member function to notificate the observer about an
   130       /// item is added to the container.
   131       ///
   132       /// The add() member function notificates the observer about an item
   133       /// is added to the container. It have to be overrided in the
   134       /// subclasses.
   135 	
   136       virtual void add(const Item&) = 0;	
   137 
   138 
   139       /// \brief The member function to notificate the observer about an
   140       /// item is erased from the container.
   141       ///
   142       /// The erase() member function notificates the observer about an
   143       /// item is erased from the container. It have to be overrided in
   144       /// the subclasses.
   145 	
   146       virtual void erase(const Item&) = 0;
   147 
   148       /// \brief The member function to notificate the observer about the
   149       /// container is builded.
   150       ///
   151       /// The build() member function notificates the observer about the
   152       /// container is builded from an empty container. It have to be
   153       /// overrided in the subclasses.
   154 
   155       virtual void build() = 0;
   156 
   157       /// \brief The member function to notificate the observer about all
   158       /// items are erased from the container.
   159       ///
   160       /// The clear() member function notificates the observer about all
   161       /// items are erased from the container. It have to be overrided in
   162       /// the subclasses.
   163       
   164       virtual void clear() = 0;
   165 
   166     };
   167 	
   168   protected:
   169 	
   170 
   171     typedef std::vector<ObserverBase*> Container; 
   172 
   173     Container container;
   174 
   175 		
   176   public:
   177 
   178     /// Default constructor.
   179 	
   180     ///
   181     /// The default constructor of the AlterationNotifier. 
   182     /// It creates an empty registry.
   183     AlterationNotifier() {}
   184 
   185     /// Copy Constructor of the AlterationNotifier. 
   186 	
   187     /// Copy constructor of the AlterationNotifier. 
   188     /// It creates only an empty registry because the copiable
   189     /// registry's observers have to be registered still into that registry.
   190     AlterationNotifier(const AlterationNotifier&) {}
   191 
   192     /// Assign operator.
   193 		
   194     /// Assign operator for the AlterationNotifier. 
   195     /// It makes the notifier only empty because the copiable
   196     /// notifier's observers have to be registered still into that registry.
   197     AlterationNotifier& operator=(const AlterationNotifier&) {
   198       typename Container::iterator it;
   199       for (it = container.begin(); it != container.end(); ++it) {
   200 	(*it)->registry = 0;
   201       }
   202     }
   203 
   204     /// Destructor.
   205 				
   206     /// Destructor of the AlterationNotifier.
   207     ///
   208     ~AlterationNotifier() {
   209       typename Container::iterator it;
   210       for (it = container.begin(); it != container.end(); ++it) {
   211 	(*it)->registry = 0;
   212       }
   213     }
   214 	
   215 	
   216   protected:
   217 
   218     void attach(ObserverBase& observer) {
   219       container.push_back(&observer);
   220       observer.registry = this;
   221       observer.registry_index = container.size()-1;
   222     } 
   223 
   224     void detach(ObserverBase& base) {
   225       container.back()->registry_index = base.registry_index; 
   226       container[base.registry_index] = container.back();
   227       container.pop_back();
   228       base.registry = 0;
   229     }
   230 
   231   public:
   232 	
   233     /// Notifies all the registered observers about an Item added to the container.
   234 		
   235     /// It notifies all the registered observers about an Item added to the container.
   236     /// 
   237     void add(const Item& key) {
   238       typename Container::iterator it;
   239       for (it = container.begin(); it != container.end(); ++it) {
   240 	(*it)->add(key);
   241       }
   242     }	
   243 
   244     /// Notifies all the registered observers about an Item erased from the container.
   245 		
   246     /// It notifies all the registered observers about an Item erased from the container.
   247     /// 
   248     void erase(const Item& key) {
   249       typename Container::iterator it;
   250       for (it = container.begin(); it != container.end(); ++it) {
   251 	(*it)->erase(key);
   252       }
   253     }
   254     
   255 
   256     /// Notifies all the registered observers about the container is builded.
   257 		
   258     /// Notifies all the registered observers about the container is builded
   259     /// from an empty container.
   260     void build() {
   261       typename Container::iterator it;
   262       for (it = container.begin(); it != container.end(); ++it) {
   263 	(*it)->build();
   264       }
   265     }
   266 
   267 
   268     /// Notifies all the registered observers about all Items are erased.
   269 
   270     /// Notifies all the registered observers about all Items are erased
   271     /// from the container.
   272     void clear() {
   273       typename Container::iterator it;
   274       for (it = container.begin(); it != container.end(); ++it) {
   275 	(*it)->clear();
   276       }
   277     }
   278   };
   279 
   280 
   281   /// \brief Class to extend a graph with the functionality of alteration
   282   /// observing.
   283   ///
   284   /// AlterableGraphExtender extends the _Base graphs functionality with
   285   /// the possibility of alteration observing. It defines two observer
   286   /// registrys for the nodes and mapes.
   287   /// 
   288   /// \todo Document what "alteration observing" is. And probably find a
   289   /// better (shorter) name.
   290   ///
   291   /// \param _Base is the base class to extend.
   292   ///
   293   /// \pre _Base is conform to the BaseGraphComponent concept.
   294   ///
   295   /// \post AlterableGraphExtender<_Base> is conform to the
   296   /// AlterableGraphComponent concept.
   297   ///
   298   /// \author Balazs Dezso
   299 
   300   template <typename _Base> 
   301   class AlterableGraphExtender : public _Base {
   302   public:
   303 
   304     typedef AlterableGraphExtender Graph;
   305     typedef _Base Parent;
   306 
   307     typedef typename Parent::Node Node;
   308     typedef typename Parent::Edge Edge;
   309 
   310     /// The edge observer registry.
   311     typedef AlterationNotifier<Edge> EdgeNotifier;
   312     /// The node observer registry.
   313     typedef AlterationNotifier<Node> NodeNotifier;
   314 
   315 
   316   protected:
   317 
   318     mutable EdgeNotifier edge_notifier;
   319 
   320     mutable NodeNotifier node_notifier;
   321 
   322   public:
   323 
   324     /// \brief Gives back the edge alteration notifier.
   325     ///
   326     /// Gives back the edge alteration notifier.
   327     EdgeNotifier& getNotifier(Edge) const {
   328       return edge_notifier;
   329     }
   330 
   331     /// \brief Gives back the node alteration notifier.
   332     ///
   333     /// Gives back the node alteration notifier.
   334     NodeNotifier& getNotifier(Node) const {
   335       return node_notifier;
   336     }
   337 
   338     ~AlterableGraphExtender() {
   339       node_notifier.clear();
   340       edge_notifier.clear();
   341     }
   342     
   343   };
   344 
   345   /// \brief Class to extend an undirected graph with the functionality of
   346   /// alteration observing.
   347   ///
   348   /// \todo Document.
   349   ///
   350   /// \sa AlterableGraphExtender
   351   ///
   352   /// \bug This should be done some other way. Possibilities: template
   353   /// specialization (not very easy, if at all possible); some kind of
   354   /// enable_if boost technique?
   355 
   356   template <typename _Base> 
   357   class AlterableUndirGraphExtender
   358     : public AlterableGraphExtender<_Base> {
   359   public:
   360 
   361     typedef AlterableUndirGraphExtender Graph;
   362     typedef AlterableGraphExtender<_Base> Parent;
   363 
   364     typedef typename Parent::UndirEdge UndirEdge;
   365 
   366     /// The edge observer registry.
   367     typedef AlterationNotifier<UndirEdge> UndirEdgeNotifier;
   368 
   369   protected:
   370 
   371     mutable UndirEdgeNotifier undir_edge_notifier;
   372 
   373   public:
   374 
   375     using Parent::getNotifier;
   376     UndirEdgeNotifier& getNotifier(UndirEdge) const {
   377       return undir_edge_notifier;
   378     }
   379 
   380     ~AlterableUndirGraphExtender() {
   381       undir_edge_notifier.clear();
   382     }
   383   };
   384   
   385 /// @}
   386   
   387 
   388 }
   389 
   390 #endif