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