src/lemon/bits/alteration_notifier.h
author ladanyi
Mon, 18 Apr 2005 17:23:42 +0000
changeset 1369 f1cf6b807414
parent 1311 b810a07248a0
child 1414 01d9d6bc1284
permissions -rw-r--r--
irrelevant changes
     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 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 graphmaps
    24 ///\file
    25 ///\brief Observer registry for graph alteration observers.
    26 
    27 namespace lemon {
    28 
    29   /// \addtogroup graphmaps
    30   /// @{
    31 
    32   /// Registry class to register objects observes alterations in the graph.
    33 
    34   /// This class is a registry for the objects which observe the
    35   /// alterations in a container. The alteration observers can be attached
    36   /// to and detached from the registry. The observers have to inherit
    37   /// from the \ref AlterationNotifier::ObserverBase and override
    38   /// the virtual functions in that.
    39   ///
    40   /// The most important application of the alteration observing is the
    41   /// dynamic map implementation when the observers are observing the
    42   /// alterations in the graph.
    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       /// Default constructor.
    78 
    79       /// Default constructor for ObserverBase.
    80       /// 
    81       ObserverBase() : registry(0) {}
    82 
    83       virtual ~ObserverBase() {}
    84 
    85       /// 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       /// 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 
   137       /// \brief The member function to notificate the observer about an
   138       /// item is erased from the container.
   139       ///
   140       /// The erase() member function notificates the observer about an
   141       /// item is erased from the container. It have to be overrided in
   142       /// the subclasses.
   143 	
   144       virtual void erase(const Item&) = 0;
   145 
   146       /// \brief The member function to notificate the observer about the
   147       /// container is built.
   148       ///
   149       /// The build() member function notificates the observer about the
   150       /// container is built from an empty container. It have to be
   151       /// overrided in the subclasses.
   152 
   153       virtual void build() = 0;
   154 
   155       /// \brief The member function to notificate the observer about all
   156       /// items are erased from the container.
   157       ///
   158       /// The clear() member function notificates the observer about all
   159       /// items are erased from the container. It have to be overrided in
   160       /// the subclasses.
   161       
   162       virtual void clear() = 0;
   163 
   164     };
   165 	
   166   protected:
   167 	
   168 
   169     typedef std::vector<ObserverBase*> Container; 
   170 
   171     Container container;
   172 
   173 		
   174   public:
   175 
   176     /// Default constructor.
   177 	
   178     ///
   179     /// The default constructor of the AlterationNotifier. 
   180     /// It creates an empty registry.
   181     AlterationNotifier() {}
   182 
   183     /// Copy Constructor of the AlterationNotifier. 
   184 	
   185     /// Copy constructor of the AlterationNotifier. 
   186     /// It creates only an empty registry because the copiable
   187     /// registry's observers have to be registered still into that registry.
   188     AlterationNotifier(const AlterationNotifier&) {}
   189 
   190     /// Assign operator.
   191 		
   192     /// Assign operator for the AlterationNotifier. 
   193     /// It makes the notifier only empty because the copiable
   194     /// notifier's observers have to be registered still into that registry.
   195     AlterationNotifier& operator=(const AlterationNotifier&) {
   196       typename Container::iterator it;
   197       for (it = container.begin(); it != container.end(); ++it) {
   198 	(*it)->registry = 0;
   199       }
   200     }
   201 
   202     /// Destructor.
   203 				
   204     /// Destructor of the AlterationNotifier.
   205     ///
   206     ~AlterationNotifier() {
   207       typename Container::iterator it;
   208       for (it = container.begin(); it != container.end(); ++it) {
   209 	(*it)->registry = 0;
   210       }
   211     }
   212 	
   213 	
   214   protected:
   215 
   216     void attach(ObserverBase& observer) {
   217       container.push_back(&observer);
   218       observer.registry = this;
   219       observer.registry_index = container.size()-1;
   220     } 
   221 
   222     void detach(ObserverBase& base) {
   223       container.back()->registry_index = base.registry_index; 
   224       container[base.registry_index] = container.back();
   225       container.pop_back();
   226       base.registry = 0;
   227     }
   228 
   229   public:
   230 	
   231     /// Notifies all the registered observers about an Item added to the container.
   232 		
   233     /// It notifies all the registered observers about an Item added to the container.
   234     /// 
   235     void add(const Item& key) {
   236       typename Container::iterator it;
   237       for (it = container.begin(); it != container.end(); ++it) {
   238 	(*it)->add(key);
   239       }
   240     }	
   241 
   242     /// Notifies all the registered observers about an Item erased from the container.
   243 		
   244     /// It notifies all the registered observers about an Item erased from the container.
   245     /// 
   246     void erase(const Item& key) {
   247       typename Container::iterator it;
   248       for (it = container.begin(); it != container.end(); ++it) {
   249 	(*it)->erase(key);
   250       }
   251     }
   252     
   253 
   254     /// Notifies all the registered observers about the container is built.
   255 		
   256     /// Notifies all the registered observers about the container is built
   257     /// from an empty container.
   258     void build() {
   259       typename Container::iterator it;
   260       for (it = container.begin(); it != container.end(); ++it) {
   261 	(*it)->build();
   262       }
   263     }
   264 
   265 
   266     /// Notifies all the registered observers about all Items are erased.
   267 
   268     /// Notifies all the registered observers about all Items are erased
   269     /// from the container.
   270     void clear() {
   271       typename Container::iterator it;
   272       for (it = container.begin(); it != container.end(); ++it) {
   273 	(*it)->clear();
   274       }
   275     }
   276   };
   277 
   278 
   279   /// \brief Class to extend a graph with the functionality of alteration
   280   /// observing.
   281   ///
   282   /// AlterableGraphExtender extends the _Base graphs functionality with
   283   /// the possibility of alteration observing. It defines two observer
   284   /// registrys for the nodes and mapes.
   285   /// 
   286   /// \todo Document what "alteration observing" is. And probably find a
   287   /// better (shorter) name.
   288   ///
   289   /// \param _Base is the base class to extend.
   290   ///
   291   /// \pre _Base is conform to the BaseGraphComponent concept.
   292   ///
   293   /// \post AlterableGraphExtender<_Base> is conform to the
   294   /// AlterableGraphComponent concept.
   295   ///
   296   /// \author Balazs Dezso
   297 
   298   template <typename _Base> 
   299   class AlterableGraphExtender : public _Base {
   300   public:
   301 
   302     typedef AlterableGraphExtender Graph;
   303     typedef _Base Parent;
   304 
   305     typedef typename Parent::Node Node;
   306     typedef typename Parent::Edge Edge;
   307 
   308     /// The edge observer registry.
   309     typedef AlterationNotifier<Edge> EdgeNotifier;
   310     /// The node observer registry.
   311     typedef AlterationNotifier<Node> NodeNotifier;
   312 
   313 
   314   protected:
   315 
   316     mutable EdgeNotifier edge_notifier;
   317 
   318     mutable NodeNotifier node_notifier;
   319 
   320   public:
   321 
   322     /// \brief Gives back the edge alteration notifier.
   323     ///
   324     /// Gives back the edge alteration notifier.
   325     EdgeNotifier& getNotifier(Edge) const {
   326       return edge_notifier;
   327     }
   328 
   329     /// \brief Gives back the node alteration notifier.
   330     ///
   331     /// Gives back the node alteration notifier.
   332     NodeNotifier& getNotifier(Node) const {
   333       return node_notifier;
   334     }
   335 
   336     ~AlterableGraphExtender() {
   337       node_notifier.clear();
   338       edge_notifier.clear();
   339     }
   340     
   341   };
   342 
   343   /// \brief Class to extend an undirected graph with the functionality of
   344   /// alteration observing.
   345   ///
   346   /// \todo Document.
   347   ///
   348   /// \sa AlterableGraphExtender
   349   ///
   350   /// \bug This should be done some other way. Possibilities: template
   351   /// specialization (not very easy, if at all possible); some kind of
   352   /// enable_if boost technique?
   353 
   354   template <typename _Base> 
   355   class AlterableUndirGraphExtender
   356     : public AlterableGraphExtender<_Base> {
   357   public:
   358 
   359     typedef AlterableUndirGraphExtender Graph;
   360     typedef AlterableGraphExtender<_Base> Parent;
   361 
   362     typedef typename Parent::UndirEdge UndirEdge;
   363 
   364     /// The edge observer registry.
   365     typedef AlterationNotifier<UndirEdge> UndirEdgeNotifier;
   366 
   367   protected:
   368 
   369     mutable UndirEdgeNotifier undir_edge_notifier;
   370 
   371   public:
   372 
   373     using Parent::getNotifier;
   374     UndirEdgeNotifier& getNotifier(UndirEdge) const {
   375       return undir_edge_notifier;
   376     }
   377 
   378     ~AlterableUndirGraphExtender() {
   379       undir_edge_notifier.clear();
   380     }
   381   };
   382   
   383 /// @}
   384   
   385 
   386 }
   387 
   388 #endif