14 * express or implied, and with no claim as to its suitability for any |
14 * express or implied, and with no claim as to its suitability for any |
15 * purpose. |
15 * purpose. |
16 * |
16 * |
17 */ |
17 */ |
18 |
18 |
19 #ifndef LEMON_ALTERATION_NOTIFIER_H |
19 #ifndef LEMON_BITS_ALTERATION_NOTIFIER_H |
20 #define LEMON_ALTERATION_NOTIFIER_H |
20 #define LEMON_BITS_ALTERATION_NOTIFIER_H |
21 |
21 |
22 #include <vector> |
22 #include <vector> |
23 #include <algorithm> |
23 |
|
24 #include <lemon/bits/utility.h> |
24 |
25 |
25 ///\ingroup graphbits |
26 ///\ingroup graphbits |
26 ///\file |
27 ///\file |
27 ///\brief Observer registry for graph alteration observers. |
28 ///\brief Observer notifier for graph alteration observers. |
28 |
29 |
29 namespace lemon { |
30 namespace lemon { |
30 |
31 |
31 /// \addtogroup graphbits |
32 /// \ingroup graphbits |
32 /// @{ |
33 /// |
33 |
34 /// \brief Notifier class to notify observes about alterations in |
34 /// \brief Registry class to register objects observes alterations in |
35 /// a container. |
35 /// the graph. |
36 /// |
36 /// |
37 /// The simple graph's can be refered as two containers, one node container |
37 /// This class is a registry for the objects which observe the |
38 /// and one edge container. But they are not standard containers they |
38 /// alterations in a container. The alteration observers can be attached |
39 /// does not store values directly they are just key continars for more |
39 /// to and detached from the registry. The observers have to inherit |
40 /// value containers which are the node and edge maps. |
40 /// from the \ref AlterationNotifier::ObserverBase and override |
41 /// |
41 /// the virtual functions in that. |
42 /// The graph's node and edge sets can be changed as we add or erase |
42 /// |
43 /// nodes and edges in the graph. Lemon would like to handle easily |
43 /// The most important application of the alteration observing is the |
44 /// that the node and edge maps should contain values for all nodes or |
44 /// dynamic map implementation. |
45 /// edges. If we want to check on every indicing if the map contains |
45 /// |
46 /// the current indicing key that cause a drawback in the performance |
46 /// \param _Item The item type what the observers are observing, usually |
47 /// in the library. We use an other solution we notify all maps about |
47 /// edge or node. |
48 /// an alteration in the graph, which cause only drawback on the |
|
49 /// alteration of the graph. |
|
50 /// |
|
51 /// This class provides an interface to the container. The \e first() and \e |
|
52 /// next() member functions make possible to iterate on the keys of the |
|
53 /// container. The \e id() function returns an integer id for each key. |
|
54 /// The \e maxId() function gives back an upper bound of the ids. |
|
55 /// |
|
56 /// For the proper functonality of this class, we should notify it |
|
57 /// about each alteration in the container. The alterations have four type |
|
58 /// as \e add(), \e erase(), \e build() and \e clear(). The \e add() and |
|
59 /// \e erase() signals that only one or few items added or erased to or |
|
60 /// from the graph. If all items are erased from the graph or from an empty |
|
61 /// graph a new graph is builded then it can be signaled with the |
|
62 /// clear() and build() members. Important rule that if we erase items |
|
63 /// from graph we should first signal the alteration and after that erase |
|
64 /// them from the container, on the other way on item addition we should |
|
65 /// first extend the container and just after that signal the alteration. |
|
66 /// |
|
67 /// The alteration can be observed with a class inherited from the |
|
68 /// \e ObserverBase nested class. The signals can be handled with |
|
69 /// overriding the virtual functions defined in the base class. |
|
70 /// The observer base can be attached to the notifier with the |
|
71 /// \e attach() member and can be detached with detach() function. |
|
72 /// |
|
73 /// Alteration observers try to be exception safe. This can be achived |
|
74 /// when the observers does not throw exception on \e erase() and |
|
75 /// \e clear(). Less strict condition is that the \e erase() should |
|
76 /// not throw exception after an \e add() with the same parameter and |
|
77 /// the \e clear() should not throw exception after a \e build(). |
|
78 /// |
|
79 /// There are some place when the alteration observing is not completly |
|
80 /// reliable. If we want to carry out the node degree in the graph |
|
81 /// as in the \ref InDegMap and we use the reverseEdge that cause |
|
82 /// unreliable functionality. Because the alteration observing signals |
|
83 /// only erasing and adding but not the reversing it will stores bad |
|
84 /// degrees. The sub graph adaptors cannot signal the alterations because |
|
85 /// just a setting in the filter map can modify the graph and this cannot |
|
86 /// be watched in any way. |
|
87 /// |
|
88 /// \param _Container The container which is observed. |
|
89 /// \param _Item The item type which is obserbved. |
48 /// |
90 /// |
49 /// \author Balazs Dezso |
91 /// \author Balazs Dezso |
50 |
92 |
51 template <typename _Item> |
93 template <typename _Container, typename _Item> |
52 class AlterationNotifier { |
94 class AlterationNotifier { |
53 public: |
95 public: |
54 |
96 |
55 typedef True Notifier; |
97 typedef True Notifier; |
56 |
98 |
|
99 typedef _Container Container; |
57 typedef _Item Item; |
100 typedef _Item Item; |
58 |
101 |
59 /// ObserverBase is the base class for the observers. |
102 /// \brief ObserverBase is the base class for the observers. |
60 |
103 /// |
61 /// ObserverBase is the abstract base class for the observers. |
104 /// ObserverBase is the abstract base class for the observers. |
62 /// It will be notified about an item was inserted into or |
105 /// It will be notified about an item was inserted into or |
63 /// erased from the graph. |
106 /// erased from the graph. |
64 /// |
107 /// |
65 /// The observer interface contains some pure virtual functions |
108 /// The observer interface contains some pure virtual functions |
73 /// |
116 /// |
74 /// \author Balazs Dezso |
117 /// \author Balazs Dezso |
75 |
118 |
76 class ObserverBase { |
119 class ObserverBase { |
77 protected: |
120 protected: |
78 typedef AlterationNotifier Registry; |
121 typedef AlterationNotifier Notifier; |
79 |
122 |
80 friend class AlterationNotifier; |
123 friend class AlterationNotifier; |
81 |
124 |
82 /// \brief Default constructor. |
125 /// \brief Default constructor. |
83 /// |
126 /// |
84 /// Default constructor for ObserverBase. |
127 /// Default constructor for ObserverBase. |
85 /// |
128 /// |
86 ObserverBase() : registry(0) {} |
129 ObserverBase() : notifier(0) {} |
87 |
130 |
|
131 /// \brief Constructor which attach the observer into notifier. |
|
132 /// |
|
133 /// Constructor which attach the observer into notifier. |
|
134 ObserverBase(AlterationNotifier& _notifier) { |
|
135 attach(_notifier); |
|
136 } |
|
137 |
|
138 /// \brief Constructor which attach the obserever to the same notifier. |
|
139 /// |
|
140 /// Constructor which attach the obserever to the same notifier as |
|
141 /// the other observer is attached to. |
88 ObserverBase(const ObserverBase& copy) { |
142 ObserverBase(const ObserverBase& copy) { |
89 if (copy.attached()) { |
143 if (copy.attached()) { |
90 copy.getRegistry()->attach(*this); |
144 attach(*copy.getNotifier()); |
91 } |
145 } |
92 } |
146 } |
93 |
147 |
94 virtual ~ObserverBase() {} |
148 /// \brief Destructor |
|
149 virtual ~ObserverBase() { |
|
150 if (attached()) { |
|
151 detach(); |
|
152 } |
|
153 } |
95 |
154 |
96 /// \brief Attaches the observer into an AlterationNotifier. |
155 /// \brief Attaches the observer into an AlterationNotifier. |
97 /// |
156 /// |
98 /// This member attaches the observer into an AlterationNotifier. |
157 /// This member attaches the observer into an AlterationNotifier. |
99 /// |
158 /// |
100 void attach(AlterationNotifier& r) { |
159 void attach(AlterationNotifier& _notifier) { |
101 registry = &r; |
160 notifier = &_notifier; |
102 registry->attach(*this); |
161 notifier->attach(*this); |
103 } |
162 } |
104 |
163 |
105 /// \brief Detaches the observer into an AlterationNotifier. |
164 /// \brief Detaches the observer into an AlterationNotifier. |
106 /// |
165 /// |
107 /// This member detaches the observer from an AlterationNotifier. |
166 /// This member detaches the observer from an AlterationNotifier. |
108 /// |
167 /// |
109 void detach() { |
168 void detach() { |
110 if (registry) { |
169 notifier->detach(*this); |
111 registry->detach(*this); |
170 } |
112 } |
171 |
113 } |
172 |
114 |
173 /// \brief Gives back a pointer to the notifier which the map |
115 |
|
116 /// Gives back a pointer to the registry what the map attached into. |
|
117 |
|
118 /// This function gives back a pointer to the registry what the map |
|
119 /// attached into. |
174 /// attached into. |
120 /// |
175 /// |
121 Registry* getRegistry() const { return const_cast<Registry*>(registry); } |
176 /// This function gives back a pointer to the notifier which the map |
|
177 /// attached into. |
|
178 /// |
|
179 Notifier* getNotifier() const { return const_cast<Notifier*>(notifier); } |
122 |
180 |
123 /// Gives back true when the observer is attached into a registry. |
181 /// Gives back true when the observer is attached into a notifier. |
124 bool attached() const { return registry != 0; } |
182 bool attached() const { return notifier != 0; } |
125 |
183 |
126 private: |
184 private: |
127 |
185 |
128 ObserverBase& operator=(const ObserverBase& copy); |
186 ObserverBase& operator=(const ObserverBase& copy); |
129 |
187 |
130 protected: |
188 protected: |
131 |
189 |
132 Registry* registry; |
190 Notifier* notifier; |
133 int registry_index; |
191 int notifier_index; |
134 |
192 |
135 /// \brief The member function to notificate the observer about an |
193 /// \brief The member function to notificate the observer about an |
136 /// item is added to the container. |
194 /// item is added to the container. |
137 /// |
195 /// |
138 /// The add() member function notificates the observer about an item |
196 /// The add() member function notificates the observer about an item |
168 /// |
234 /// |
169 /// The erase() member function notificates the observer about more item |
235 /// The erase() member function notificates the observer about more item |
170 /// is erased from the container. It have to be overrided in the |
236 /// is erased from the container. It have to be overrided in the |
171 /// subclasses. |
237 /// subclasses. |
172 virtual void erase(const std::vector<Item>& items) { |
238 virtual void erase(const std::vector<Item>& items) { |
173 for (int i = 0; i < (int)items.size(); ++i) { |
239 for (int i = 0; i < (int)items.size(); ++i) { |
174 erase(items[i]); |
240 erase(items[i]); |
175 } |
241 } |
176 } |
242 } |
177 |
243 |
178 /// \brief The member function to notificate the observer about the |
244 /// \brief The member function to notificate the observer about the |
179 /// container is built. |
245 /// container is built. |
180 /// |
246 /// |
181 /// The build() member function notificates the observer about the |
247 /// The build() member function notificates the observer about the |
182 /// container is built from an empty container. It have to be |
248 /// container is built from an empty container. It have to be |
183 /// overrided in the subclasses. |
249 /// overrided in the subclasses. |
184 |
250 |
185 virtual void build() = 0; |
251 virtual void build() { |
|
252 Item it; |
|
253 try { |
|
254 for (notifier->first(it); it != INVALID; notifier->next(it)) { |
|
255 add(it); |
|
256 } |
|
257 } catch (...) { |
|
258 Item jt; |
|
259 for (notifier->first(jt); jt != it; notifier->next(jt)) { |
|
260 erase(jt); |
|
261 } |
|
262 throw; |
|
263 } |
|
264 } |
186 |
265 |
187 /// \brief The member function to notificate the observer about all |
266 /// \brief The member function to notificate the observer about all |
188 /// items are erased from the container. |
267 /// items are erased from the container. |
189 /// |
268 /// |
190 /// The clear() member function notificates the observer about all |
269 /// The clear() member function notificates the observer about all |
191 /// items are erased from the container. It have to be overrided in |
270 /// items are erased from the container. It have to be overrided in |
192 /// the subclasses. |
271 /// the subclasses. |
193 |
272 virtual void clear() { |
194 virtual void clear() = 0; |
273 Item it; |
|
274 for (notifier->first(it); it != INVALID; notifier->next(it)) { |
|
275 erase(it); |
|
276 } |
|
277 } |
195 |
278 |
196 }; |
279 }; |
197 |
280 |
198 protected: |
281 protected: |
199 |
282 |
200 |
283 const Container* container; |
201 typedef std::vector<ObserverBase*> Container; |
284 |
202 |
285 typedef std::vector<ObserverBase*> Observers; |
203 Container container; |
286 Observers observers; |
204 |
287 |
205 |
288 |
206 public: |
289 public: |
207 |
290 |
208 /// Default constructor. |
291 /// \brief Default constructor. |
209 |
|
210 /// |
292 /// |
211 /// The default constructor of the AlterationNotifier. |
293 /// The default constructor of the AlterationNotifier. |
212 /// It creates an empty registry. |
294 /// It creates an empty notifier. |
213 AlterationNotifier() {} |
295 AlterationNotifier() |
214 |
296 : container(0) {} |
215 /// Copy Constructor of the AlterationNotifier. |
297 |
216 |
298 /// \brief Constructor. |
|
299 /// |
|
300 /// Constructor with the observed container parameter. |
|
301 AlterationNotifier(const Container& _container) |
|
302 : container(&_container) {} |
|
303 |
|
304 /// \brief Copy Constructor of the AlterationNotifier. |
|
305 /// |
217 /// Copy constructor of the AlterationNotifier. |
306 /// Copy constructor of the AlterationNotifier. |
218 /// It creates only an empty registry because the copiable |
307 /// It creates only an empty notifier because the copiable |
219 /// registry's observers have to be registered still into that registry. |
308 /// notifier's observers have to be registered still into that notifier. |
220 AlterationNotifier(const AlterationNotifier&) {} |
309 AlterationNotifier(const AlterationNotifier& _notifier) |
221 |
310 : container(_notifier.container) {} |
222 /// Assign operator. |
311 |
|
312 /// \brief Destructor. |
|
313 /// |
|
314 /// Destructor of the AlterationNotifier. |
|
315 /// |
|
316 ~AlterationNotifier() { |
|
317 typename Observers::iterator it; |
|
318 for (it = observers.begin(); it != observers.end(); ++it) { |
|
319 (*it)->notifier = 0; |
|
320 } |
|
321 } |
|
322 |
|
323 /// \brief Sets the container. |
|
324 /// |
|
325 /// Sets the container. |
|
326 void setContainer(const Container& _container) { |
|
327 container = &_container; |
|
328 } |
|
329 |
|
330 protected: |
|
331 |
|
332 AlterationNotifier& operator=(const AlterationNotifier&); |
|
333 |
|
334 public: |
|
335 |
|
336 |
|
337 |
|
338 /// \brief First item in the container. |
|
339 /// |
|
340 /// Returns the first item in the container. It is |
|
341 /// for start the iteration on the container. |
|
342 void first(Item& item) const { |
|
343 container->first(item); |
|
344 } |
|
345 |
|
346 /// \brief Next item in the container. |
|
347 /// |
|
348 /// Returns the next item in the container. It is |
|
349 /// for iterate on the container. |
|
350 void next(Item& item) const { |
|
351 container->next(item); |
|
352 } |
|
353 |
|
354 /// \brief Returns the id of the item. |
|
355 /// |
|
356 /// Returns the id of the item provided by the container. |
|
357 int id(const Item& item) const { |
|
358 return container->id(item); |
|
359 } |
|
360 |
|
361 /// \brief Returns the maximum id of the container. |
|
362 /// |
|
363 /// Returns the maximum id of the container. |
|
364 int maxId() const { |
|
365 return container->maxId(Item()); |
|
366 } |
223 |
367 |
224 /// Assign operator for the AlterationNotifier. |
|
225 /// It makes the notifier only empty because the copiable |
|
226 /// notifier's observers have to be registered still into that registry. |
|
227 AlterationNotifier& operator=(const AlterationNotifier&) { |
|
228 typename Container::iterator it; |
|
229 for (it = container.begin(); it != container.end(); ++it) { |
|
230 (*it)->registry = 0; |
|
231 } |
|
232 } |
|
233 |
|
234 /// Destructor. |
|
235 |
|
236 /// Destructor of the AlterationNotifier. |
|
237 /// |
|
238 ~AlterationNotifier() { |
|
239 typename Container::iterator it; |
|
240 for (it = container.begin(); it != container.end(); ++it) { |
|
241 (*it)->registry = 0; |
|
242 } |
|
243 } |
|
244 |
|
245 |
|
246 protected: |
368 protected: |
247 |
369 |
248 void attach(ObserverBase& observer) { |
370 void attach(ObserverBase& observer) { |
249 container.push_back(&observer); |
371 observers.push_back(&observer); |
250 observer.registry = this; |
372 observer.notifier = this; |
251 observer.registry_index = container.size()-1; |
373 observer.notifier_index = observers.size() - 1; |
252 } |
374 } |
253 |
375 |
254 void detach(ObserverBase& base) { |
376 void detach(ObserverBase& observer) { |
255 container.back()->registry_index = base.registry_index; |
377 observers.back()->notifier_index = observer.notifier_index; |
256 container[base.registry_index] = container.back(); |
378 observers[observer.notifier_index] = observers.back(); |
257 container.pop_back(); |
379 observers.pop_back(); |
258 base.registry = 0; |
380 observer.notifier = 0; |
259 } |
381 } |
260 |
382 |
261 public: |
383 public: |
262 |
384 |
263 /// \brief Notifies all the registered observers about an Item added to |
385 /// \brief Notifies all the registed observers about an item added to |
264 /// the container. |
386 /// the container. |
265 /// |
387 /// |
266 /// It notifies all the registered observers about an Item added to |
388 /// It notifies all the registed observers about an item added to |
267 /// the container. |
389 /// the container. |
268 /// |
390 /// |
269 void add(const Item& item) { |
391 void add(const Item& item) { |
270 typename Container::iterator it; |
392 typename Observers::iterator it; |
271 try { |
393 try { |
272 for (it = container.begin(); it != container.end(); ++it) { |
394 for (it = observers.begin(); it != observers.end(); ++it) { |
273 (*it)->add(item); |
395 (*it)->add(item); |
274 } |
396 } |
275 } catch (...) { |
397 } catch (...) { |
276 typename Container::iterator jt; |
398 typename Observers::iterator jt; |
277 for (jt = container.begin(); jt != it; ++it) { |
399 for (jt = observers.begin(); jt != it; ++jt) { |
278 (*it)->erase(item); |
400 (*it)->erase(item); |
279 } |
401 } |
280 throw; |
402 throw; |
281 } |
403 } |
282 } |
404 } |
283 |
405 |
284 /// \brief Notifies all the registered observers about more Item added to |
406 /// \brief Notifies all the registed observers about more item added to |
285 /// the container. |
407 /// the container. |
286 /// |
408 /// |
287 /// It notifies all the registered observers about more Item added to |
409 /// It notifies all the registed observers about more item added to |
288 /// the container. |
410 /// the container. |
289 /// |
411 /// |
290 void add(const std::vector<Item>& items) { |
412 void add(const std::vector<Item>& items) { |
291 typename Container::iterator it; |
413 typename Observers::iterator it; |
292 try { |
414 try { |
293 for (it = container.begin(); it != container.end(); ++it) { |
415 for (it = observers.begin(); it != observers.end(); ++it) { |
294 (*it)->add(items); |
416 (*it)->add(items); |
295 } |
417 } |
296 } catch (...) { |
418 } catch (...) { |
297 typename Container::iterator jt; |
419 typename Observers::iterator jt; |
298 for (jt = container.begin(); jt != it; ++it) { |
420 for (jt = observers.begin(); jt != it; ++jt) { |
299 (*it)->erase(items); |
421 (*it)->erase(items); |
300 } |
422 } |
301 throw; |
423 throw; |
302 } |
424 } |
303 } |
425 } |
304 |
426 |
305 /// \brief Notifies all the registered observers about an Item erased from |
427 /// \brief Notifies all the registed observers about an item erased from |
306 /// the container. |
428 /// the container. |
307 /// |
429 /// |
308 /// It notifies all the registered observers about an Item erased from |
430 /// It notifies all the registed observers about an item erased from |
309 /// the container. |
431 /// the container. |
310 /// |
432 /// |
311 void erase(const Item& key) { |
433 void erase(const Item& key) { |
312 typename Container::iterator it; |
434 typename Observers::iterator it; |
313 for (it = container.begin(); it != container.end(); ++it) { |
435 for (it = observers.begin(); it != observers.end(); ++it) { |
314 (*it)->erase(key); |
436 (*it)->erase(key); |
315 } |
437 } |
316 } |
438 } |
317 |
439 |
318 /// \brief Notifies all the registered observers about more Item erased |
440 /// \brief Notifies all the registed observers about more item erased |
319 /// from the container. |
441 /// from the container. |
320 /// |
442 /// |
321 /// It notifies all the registered observers about more Item erased from |
443 /// It notifies all the registed observers about more item erased from |
322 /// the container. |
444 /// the container. |
323 /// |
445 /// |
324 void erase(const std::vector<Item>& items) { |
446 void erase(const std::vector<Item>& items) { |
325 typename Container::iterator it; |
447 typename Observers::iterator it; |
326 for (it = container.begin(); it != container.end(); ++it) { |
448 for (it = observers.begin(); it != observers.end(); ++it) { |
327 (*it)->erase(items); |
449 (*it)->erase(items); |
328 } |
450 } |
329 } |
451 } |
330 |
452 |
331 /// \brief Notifies all the registered observers about the container is |
453 /// \brief Notifies all the registed observers about the container is |
332 /// built. |
454 /// built. |
333 /// |
455 /// |
334 /// Notifies all the registered observers about the container is built |
456 /// Notifies all the registed observers about the container is built |
335 /// from an empty container. |
457 /// from an empty container. |
336 void build() { |
458 void build() { |
337 typename Container::iterator it; |
459 typename Observers::iterator it; |
338 try { |
460 try { |
339 for (it = container.begin(); it != container.end(); ++it) { |
461 for (it = observers.begin(); it != observers.end(); ++it) { |
340 (*it)->build(); |
462 (*it)->build(); |
341 } |
463 } |
342 } catch (...) { |
464 } catch (...) { |
343 typename Container::iterator jt; |
465 typename Observers::iterator jt; |
344 for (jt = container.begin(); jt != it; ++it) { |
466 for (jt = observers.begin(); jt != it; ++jt) { |
345 (*it)->clear(); |
467 (*it)->clear(); |
346 } |
468 } |
347 throw; |
469 throw; |
348 } |
470 } |
349 } |
471 } |
350 |
472 |
351 |
473 |
352 /// \brief Notifies all the registered observers about all Items are |
474 /// \brief Notifies all the registed observers about all items are |
353 /// erased. |
475 /// erased. |
354 /// |
476 /// |
355 /// Notifies all the registered observers about all Items are erased |
477 /// Notifies all the registed observers about all items are erased |
356 /// from the container. |
478 /// from the container. |
357 void clear() { |
479 void clear() { |
358 typename Container::iterator it; |
480 typename Observers::iterator it; |
359 for (it = container.begin(); it != container.end(); ++it) { |
481 for (it = observers.begin(); it != observers.end(); ++it) { |
360 (*it)->clear(); |
482 (*it)->clear(); |
361 } |
483 } |
362 } |
484 } |
363 }; |
485 }; |
364 |
486 |
365 |
|
366 /// @} |
|
367 |
|
368 |
|
369 } |
487 } |
370 |
488 |
371 #endif |
489 #endif |