src/work/deba/map_registry.h
author alpar
Tue, 06 Jul 2004 10:07:48 +0000
changeset 694 2d87cefb35b2
parent 627 6cc21a9c9fda
child 701 c03e073b8394
permissions -rw-r--r--
I moved run() into the body of class Dijkstra, because Doxygen handles
external member function definitions very poorly.
     1 #ifndef MAP_REGISTRY_H
     2 #define MAP_REGISTRY_H
     3 
     4 #include <vector>
     5 
     6 using namespace std;
     7 
     8 namespace hugo {
     9 
    10 /** 
    11     Registry class to register edge or node maps in the graph. The
    12     registry helps you to implement an observer pattern. If you add
    13     or erase an edge or node you must notify all the maps about the
    14     event.
    15 */
    16   template <typename G, typename K, typename KIt>
    17   class MapRegistry {
    18   public:
    19     typedef G Graph;
    20     typedef K Key;
    21     typedef KIt KeyIt;
    22 	
    23 
    24 
    25     ///. 
    26 
    27     ///. 
    28     /// 
    29     class MapBase {
    30     public:
    31       typedef G Graph;
    32       typedef MapRegistry<G, K, KIt> Registry;
    33       typedef K Key;
    34       typedef KIt KeyIt;
    35 	
    36       friend class Registry;
    37 		
    38       /** 
    39 	  Default constructor.
    40       */	
    41 		
    42       MapBase() : graph(0), registry(0) {}
    43 
    44       /** 
    45 	  Simple constructor to register into a graph registry.
    46       */
    47 	
    48       MapBase(Graph& g, Registry& r) : graph(&g), registry(0) {
    49 	r.attach(*this);
    50       }
    51 
    52       /** 
    53 	  Copy constructor with registering into the map.
    54       */	
    55 	
    56       MapBase(const MapBase& copy) : registry(0), graph(copy.graph) {
    57 	if (copy.registry) {
    58 	  copy.registry->attach(*this);
    59 	}
    60       } 
    61 	
    62       /** 
    63 	  Assign operator.
    64       */	
    65 
    66       const MapBase& operator=(const MapBase& copy) {
    67 	if (registry) {
    68 	  registry->detach(*this);
    69 	}
    70 	graph = copy.graph;
    71 	if (copy.registry) {
    72 	  copy.registry->attach(*this);
    73 	}
    74       }
    75 	
    76 
    77       /** 
    78 	  Destructor.
    79       */		
    80 
    81       virtual ~MapBase() {
    82 	if (registry) {
    83 	  registry->detach(*this);
    84 	}
    85       }
    86 	
    87     protected:
    88 		
    89       Graph* graph;
    90       Registry* registry;
    91 
    92       int registry_index;
    93 	
    94       /**
    95 	 Helper function to implement constructors in the subclasses.
    96       */
    97 	
    98       virtual void init() {
    99 	for (KeyIt it(*graph); graph->valid(it); graph->next(it)) {
   100 	  add(it);
   101 	}
   102       }
   103 	
   104       /**
   105 	 Helper function to implement the destructor in the subclasses.
   106       */
   107 	
   108       virtual void destroy() {
   109 	for (KeyIt it(*graph); graph->valid(it); graph->next(it)) {
   110 	  erase(it);
   111 	}
   112       }
   113 	
   114       /** 
   115 	  The add member function should be overloaded in the subclasses.
   116 	  \e Add extends the map with the new node.
   117       */
   118 	
   119       virtual void add(const Key&) = 0;	
   120       /** 
   121 	  The erase member function should be overloaded in the subclasses.
   122 	  \e Erase removes the node from the map.
   123       */
   124 	
   125       virtual void erase(const Key&) = 0;
   126 	
   127       /**
   128 	 Exception class to throw at unsupported operation.
   129       */
   130 	
   131       class NotSupportedOperationException {};
   132 
   133     };
   134 	
   135   protected:
   136 	
   137     typedef std::vector<MapBase*> Container; 
   138     Container container;
   139 
   140 		
   141     public:
   142 	
   143     ///. 
   144     MapRegistry() {}
   145 	
   146     ///.
   147     MapRegistry(const MapRegistry&) {}
   148 		
   149     ///.
   150     MapRegistry& operator=(const MapRegistry&) {
   151       for (it = container.begin(); it != container.end(); ++it) {
   152 	(*it)->destroy();
   153 	(*it)->graph = 0;
   154 	(*it)->registry = 0;
   155       }
   156     }
   157 				
   158     ///.
   159     ~MapRegistry() {
   160       typename Container::iterator it;
   161       for (it = container.begin(); it != container.end(); ++it) {
   162 	(*it)->destroy();
   163 	(*it)->registry = 0;
   164 	(*it)->graph = 0;
   165       }
   166     }
   167 	
   168 	
   169     public:
   170 	
   171     ///.
   172     void attach(MapBase& map) {
   173       if (map.registry) {
   174 	map.registry->detach(map);
   175       }
   176       container.push_back(&map);
   177       map.registry = this;
   178       map.registry_index = container.size()-1;
   179     } 
   180 	
   181     ///.
   182     void detach(MapBase& map) {
   183       container.back()->registry_index = map.registry_index; 
   184       container[map.registry_index] = container.back();
   185       container.pop_back();
   186       map.registry = 0;
   187       map.graph = 0;
   188     }
   189 	
   190 		
   191     ///. 
   192     virtual void add(Key& key) {
   193       typename Container::iterator it;
   194       for (it = container.begin(); it != container.end(); ++it) {
   195 	(*it)->add(key);
   196       }
   197     }	
   198 		
   199     ///.
   200     virtual void erase(Key& key) {
   201       typename Container::iterator it;
   202       for (it = container.begin(); it != container.end(); ++it) {
   203 	(*it)->erase(key);
   204       }
   205     }
   206 
   207   };
   208 
   209 }
   210 
   211 #endif