00001 /* -*- C++ -*- 00002 * lemon/notifier.h - Part of LEMON, a generic C++ optimization library 00003 * 00004 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport 00005 * (Egervary Research Group on Combinatorial Optimization, EGRES). 00006 * 00007 * Permission to use, modify and distribute this software is granted 00008 * provided that this copyright notice appears in all copies. For 00009 * precise terms see the accompanying LICENSE file. 00010 * 00011 * This software is provided "AS IS" with no warranty of any kind, 00012 * express or implied, and with no claim as to its suitability for any 00013 * purpose. 00014 * 00015 */ 00016 00017 #ifndef LEMON_ALTERATION_OBSERVER_REGISTRY_H 00018 #define LEMON_ALTERATION_OBSERVER_REGISTRY_H 00019 00020 #include <vector> 00021 #include <algorithm> 00022 00026 00027 namespace lemon { 00028 00031 00048 00049 template <typename _Item> 00050 class AlterationNotifier { 00051 public: 00052 typedef _Item Item; 00053 00055 00070 00071 class ObserverBase { 00072 protected: 00073 typedef AlterationNotifier Registry; 00074 00075 friend class AlterationNotifier; 00076 00081 ObserverBase() : registry(0) {} 00082 00083 virtual ~ObserverBase() {} 00084 00089 void attach(AlterationNotifier& r) { 00090 registry = &r; 00091 registry->attach(*this); 00092 } 00093 00098 void detach() { 00099 if (registry) { 00100 registry->detach(*this); 00101 } 00102 } 00103 00104 00106 00110 Registry* getRegistry() const { return const_cast<Registry*>(registry); } 00111 00113 bool attached() const { return registry != 0; } 00114 00115 private: 00116 00117 ObserverBase(const ObserverBase& copy); 00118 ObserverBase& operator=(const ObserverBase& copy); 00119 00120 protected: 00121 00122 Registry* registry; 00123 int registry_index; 00124 00125 public: 00126 00133 00134 virtual void add(const Item&) = 0; 00135 00142 00143 virtual void add(const std::vector<Item>& items) { 00144 for (int i = 0; i < (int)items.size(); ++i) { 00145 add(items[i]); 00146 } 00147 } 00148 00155 00156 virtual void erase(const Item&) = 0; 00157 00158 virtual void erase(const std::vector<Item>& items) { 00159 for (int i = 0; i < (int)items.size(); ++i) { 00160 add(items[i]); 00161 } 00162 } 00163 00170 00171 virtual void build() = 0; 00172 00179 00180 virtual void clear() = 0; 00181 00182 }; 00183 00184 protected: 00185 00186 00187 typedef std::vector<ObserverBase*> Container; 00188 00189 Container container; 00190 00191 00192 public: 00193 00195 00199 AlterationNotifier() {} 00200 00202 00206 AlterationNotifier(const AlterationNotifier&) {} 00207 00209 00213 AlterationNotifier& operator=(const AlterationNotifier&) { 00214 typename Container::iterator it; 00215 for (it = container.begin(); it != container.end(); ++it) { 00216 (*it)->registry = 0; 00217 } 00218 } 00219 00221 00224 ~AlterationNotifier() { 00225 typename Container::iterator it; 00226 for (it = container.begin(); it != container.end(); ++it) { 00227 (*it)->registry = 0; 00228 } 00229 } 00230 00231 00232 protected: 00233 00234 void attach(ObserverBase& observer) { 00235 container.push_back(&observer); 00236 observer.registry = this; 00237 observer.registry_index = container.size()-1; 00238 } 00239 00240 void detach(ObserverBase& base) { 00241 container.back()->registry_index = base.registry_index; 00242 container[base.registry_index] = container.back(); 00243 container.pop_back(); 00244 base.registry = 0; 00245 } 00246 00247 public: 00248 00255 void add(const Item& item) { 00256 typename Container::iterator it; 00257 for (it = container.begin(); it != container.end(); ++it) { 00258 (*it)->add(item); 00259 } 00260 } 00261 00268 void add(const std::vector<Item>& items) { 00269 typename Container::iterator it; 00270 for (it = container.begin(); it != container.end(); ++it) { 00271 (*it)->add(items); 00272 } 00273 } 00274 00281 void erase(const Item& key) { 00282 typename Container::iterator it; 00283 for (it = container.begin(); it != container.end(); ++it) { 00284 (*it)->erase(key); 00285 } 00286 } 00287 00294 void erase(const std::vector<Item>& items) { 00295 typename Container::iterator it; 00296 for (it = container.begin(); it != container.end(); ++it) { 00297 (*it)->erase(items); 00298 } 00299 } 00300 00301 00307 void build() { 00308 typename Container::iterator it; 00309 for (it = container.begin(); it != container.end(); ++it) { 00310 (*it)->build(); 00311 } 00312 } 00313 00314 00320 void clear() { 00321 typename Container::iterator it; 00322 for (it = container.begin(); it != container.end(); ++it) { 00323 (*it)->clear(); 00324 } 00325 } 00326 }; 00327 00328 00347 00348 template <typename _Base> 00349 class AlterableGraphExtender : public _Base { 00350 public: 00351 00352 typedef AlterableGraphExtender Graph; 00353 typedef _Base Parent; 00354 00355 typedef typename Parent::Node Node; 00356 typedef typename Parent::Edge Edge; 00357 00359 typedef AlterationNotifier<Edge> EdgeNotifier; 00361 typedef AlterationNotifier<Node> NodeNotifier; 00362 00363 00364 protected: 00365 00366 mutable EdgeNotifier edge_notifier; 00367 00368 mutable NodeNotifier node_notifier; 00369 00370 public: 00371 00375 EdgeNotifier& getNotifier(Edge) const { 00376 return edge_notifier; 00377 } 00378 00382 NodeNotifier& getNotifier(Node) const { 00383 return node_notifier; 00384 } 00385 00386 ~AlterableGraphExtender() { 00387 node_notifier.clear(); 00388 edge_notifier.clear(); 00389 } 00390 00391 }; 00392 00403 00404 template <typename _Base> 00405 class AlterableUndirGraphExtender 00406 : public AlterableGraphExtender<_Base> { 00407 public: 00408 00409 typedef AlterableUndirGraphExtender Graph; 00410 typedef AlterableGraphExtender<_Base> Parent; 00411 00412 typedef typename Parent::UndirEdge UndirEdge; 00413 00415 typedef AlterationNotifier<UndirEdge> UndirEdgeNotifier; 00416 00417 protected: 00418 00419 mutable UndirEdgeNotifier undir_edge_notifier; 00420 00421 public: 00422 00423 using Parent::getNotifier; 00424 UndirEdgeNotifier& getNotifier(UndirEdge) const { 00425 return undir_edge_notifier; 00426 } 00427 00428 ~AlterableUndirGraphExtender() { 00429 undir_edge_notifier.clear(); 00430 } 00431 }; 00432 00434 00435 00436 } 00437 00438 #endif