00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
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 using namespace std;
00028
00029 namespace lemon {
00030
00033
00035
00050
00051 template <typename _Item>
00052 class AlterationNotifier {
00053 public:
00054 typedef _Item Item;
00055
00057
00072
00073 class ObserverBase {
00074 protected:
00075 typedef AlterationNotifier Registry;
00076
00077 friend class AlterationNotifier;
00078
00080
00083 ObserverBase() : registry(0) {}
00084
00085 virtual ~ObserverBase() {}
00086
00088
00091 void attach(AlterationNotifier& r) {
00092 registry = &r;
00093 registry->attach(*this);
00094 }
00095
00097
00100 void detach() {
00101 if (registry) {
00102 registry->detach(*this);
00103 }
00104 }
00105
00106
00108
00112 Registry* getRegistry() const { return const_cast<Registry*>(registry); }
00113
00115 bool attached() const { return registry != 0; }
00116
00117 private:
00118
00119 ObserverBase(const ObserverBase& copy);
00120 ObserverBase& operator=(const ObserverBase& copy);
00121
00122 protected:
00123
00124 Registry* registry;
00125 int registry_index;
00126
00127 public:
00128
00135
00136 virtual void add(const Item&) = 0;
00137
00138
00145
00146 virtual void erase(const Item&) = 0;
00147
00154
00155 virtual void build() = 0;
00156
00163
00164 virtual void clear() = 0;
00165
00166 };
00167
00168 protected:
00169
00170
00171 typedef std::vector<ObserverBase*> Container;
00172
00173 Container container;
00174
00175
00176 public:
00177
00179
00183 AlterationNotifier() {}
00184
00186
00190 AlterationNotifier(const AlterationNotifier&) {}
00191
00193
00197 AlterationNotifier& operator=(const AlterationNotifier&) {
00198 typename Container::iterator it;
00199 for (it = container.begin(); it != container.end(); ++it) {
00200 (*it)->registry = 0;
00201 }
00202 }
00203
00205
00208 ~AlterationNotifier() {
00209 typename Container::iterator it;
00210 for (it = container.begin(); it != container.end(); ++it) {
00211 (*it)->registry = 0;
00212 }
00213 }
00214
00215
00216 protected:
00217
00218 void attach(ObserverBase& observer) {
00219 container.push_back(&observer);
00220 observer.registry = this;
00221 observer.registry_index = container.size()-1;
00222 }
00223
00224 void detach(ObserverBase& base) {
00225 container.back()->registry_index = base.registry_index;
00226 container[base.registry_index] = container.back();
00227 container.pop_back();
00228 base.registry = 0;
00229 }
00230
00231 public:
00232
00234
00237 void add(const Item& key) {
00238 typename Container::iterator it;
00239 for (it = container.begin(); it != container.end(); ++it) {
00240 (*it)->add(key);
00241 }
00242 }
00243
00245
00248 void erase(const Item& key) {
00249 typename Container::iterator it;
00250 for (it = container.begin(); it != container.end(); ++it) {
00251 (*it)->erase(key);
00252 }
00253 }
00254
00255
00257
00260 void build() {
00261 typename Container::iterator it;
00262 for (it = container.begin(); it != container.end(); ++it) {
00263 (*it)->build();
00264 }
00265 }
00266
00267
00269
00272 void clear() {
00273 typename Container::iterator it;
00274 for (it = container.begin(); it != container.end(); ++it) {
00275 (*it)->clear();
00276 }
00277 }
00278 };
00279
00280
00299
00300 template <typename _Base>
00301 class AlterableGraphExtender : public _Base {
00302 public:
00303
00304 typedef AlterableGraphExtender Graph;
00305 typedef _Base Parent;
00306
00307 typedef typename Parent::Node Node;
00308 typedef typename Parent::Edge Edge;
00309
00311 typedef AlterationNotifier<Edge> EdgeNotifier;
00313 typedef AlterationNotifier<Node> NodeNotifier;
00314
00315
00316 protected:
00317
00318 mutable EdgeNotifier edge_notifier;
00319
00320 mutable NodeNotifier node_notifier;
00321
00322 public:
00323
00327 EdgeNotifier& getNotifier(Edge) const {
00328 return edge_notifier;
00329 }
00330
00334 NodeNotifier& getNotifier(Node) const {
00335 return node_notifier;
00336 }
00337
00338 ~AlterableGraphExtender() {
00339 node_notifier.clear();
00340 edge_notifier.clear();
00341 }
00342
00343 };
00344
00355
00356 template <typename _Base>
00357 class AlterableUndirGraphExtender
00358 : public AlterableGraphExtender<_Base> {
00359 public:
00360
00361 typedef AlterableUndirGraphExtender Graph;
00362 typedef AlterableGraphExtender<_Base> Parent;
00363
00364 typedef typename Parent::UndirEdge UndirEdge;
00365
00367 typedef AlterationNotifier<UndirEdge> UndirEdgeNotifier;
00368
00369 protected:
00370
00371 mutable UndirEdgeNotifier undir_edge_notifier;
00372
00373 public:
00374
00375 using Parent::getNotifier;
00376 UndirEdgeNotifier& getNotifier(UndirEdge) const {
00377 return undir_edge_notifier;
00378 }
00379
00380 ~AlterableUndirGraphExtender() {
00381 undir_edge_notifier.clear();
00382 }
00383 };
00384
00386
00387
00388 }
00389
00390 #endif