64 /// them from the container, on the other way on item addition we should |
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. |
65 /// first extend the container and just after that signal the alteration. |
66 /// |
66 /// |
67 /// The alteration can be observed with a class inherited from the |
67 /// The alteration can be observed with a class inherited from the |
68 /// \e ObserverBase nested class. The signals can be handled with |
68 /// \e ObserverBase nested class. The signals can be handled with |
69 /// overriding the virtual functions defined in the base class. |
69 /// overriding the virtual functions defined in the base class. The |
70 /// The observer base can be attached to the notifier with the |
70 /// observer base can be attached to the notifier with the |
71 /// \e attach() member and can be detached with detach() function. |
71 /// \e attach() member and can be detached with detach() function. The |
72 /// |
72 /// alteration handlers should not call any function which signals |
73 /// Alteration observers try to be exception safe. This can be achived |
73 /// an other alteration in the same notifier and should not |
74 /// when the observers does not throw exception on \e erase() and |
74 /// detach any observer from the notifier. |
75 /// \e clear(). Less strict condition is that the \e erase() should |
75 /// |
76 /// not throw exception after an \e add() with the same parameter and |
76 /// Alteration observers try to be exception safe. If an \e add() or |
77 /// the \e clear() should not throw exception after a \e build(). |
77 /// a \e clear() function throws an exception then the remaining |
|
78 /// observeres will not be notified and the fulfilled additions will |
|
79 /// be rolled back by calling the \e erase() or \e clear() |
|
80 /// functions. Thence the \e erase() and \e clear() should not throw |
|
81 /// exception. Actullay, it can be throw only |
|
82 /// \ref AlterationObserver::ImmediateDetach ImmediateDetach |
|
83 /// exception which detach the observer from the notifier. |
78 /// |
84 /// |
79 /// There are some place when the alteration observing is not completly |
85 /// 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 |
86 /// 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 |
87 /// as in the \ref InDegMap and we use the reverseEdge that cause |
82 /// unreliable functionality. Because the alteration observing signals |
88 /// unreliable functionality. Because the alteration observing signals |
97 typedef True Notifier; |
103 typedef True Notifier; |
98 |
104 |
99 typedef _Container Container; |
105 typedef _Container Container; |
100 typedef _Item Item; |
106 typedef _Item Item; |
101 |
107 |
|
108 /// \brief Exception which can be called from \e clear() and |
|
109 /// \e erase(). |
|
110 /// |
|
111 /// From the \e clear() and \e erase() function only this |
|
112 /// exception is allowed to throw. The exception immediatly |
|
113 /// detaches the current observer from the notifier. Because the |
|
114 /// \e clear() and \e erase() should not throw other exceptions |
|
115 /// it can be used to invalidate the observer. |
|
116 struct ImmediateDetach {}; |
|
117 |
102 /// \brief ObserverBase is the base class for the observers. |
118 /// \brief ObserverBase is the base class for the observers. |
103 /// |
119 /// |
104 /// ObserverBase is the abstract base class for the observers. |
120 /// ObserverBase is the abstract base class for the observers. |
105 /// It will be notified about an item was inserted into or |
121 /// It will be notified about an item was inserted into or |
106 /// erased from the graph. |
122 /// erased from the graph. |
158 /// |
174 /// |
159 void attach(AlterationNotifier& _notifier) { |
175 void attach(AlterationNotifier& _notifier) { |
160 notifier = &_notifier; |
176 notifier = &_notifier; |
161 notifier->attach(*this); |
177 notifier->attach(*this); |
162 } |
178 } |
163 |
179 |
164 /// \brief Detaches the observer into an AlterationNotifier. |
180 /// \brief Detaches the observer into an AlterationNotifier. |
165 /// |
181 /// |
166 /// This member detaches the observer from an AlterationNotifier. |
182 /// This member detaches the observer from an AlterationNotifier. |
167 /// |
183 /// |
168 void detach() { |
184 void detach() { |
169 notifier->detach(*this); |
185 notifier->detach(*this); |
170 } |
186 } |
171 |
187 |
172 |
|
173 /// \brief Gives back a pointer to the notifier which the map |
188 /// \brief Gives back a pointer to the notifier which the map |
174 /// attached into. |
189 /// attached into. |
175 /// |
190 /// |
176 /// This function gives back a pointer to the notifier which the map |
191 /// This function gives back a pointer to the notifier which the map |
177 /// attached into. |
192 /// attached into. |
428 /// the container. |
443 /// the container. |
429 /// |
444 /// |
430 /// It notifies all the registed observers about an item erased from |
445 /// It notifies all the registed observers about an item erased from |
431 /// the container. |
446 /// the container. |
432 /// |
447 /// |
433 void erase(const Item& key) { |
448 void erase(const Item& key) throw() { |
434 typename Observers::iterator it; |
449 int i = 0; |
435 for (it = observers.begin(); it != observers.end(); ++it) { |
450 while (i != (int)observers.size()) { |
436 (*it)->erase(key); |
451 try { |
|
452 observers[i]->erase(key); |
|
453 ++i; |
|
454 } catch (const ImmediateDetach&) { |
|
455 observers[i]->detach(); |
|
456 } |
437 } |
457 } |
438 } |
458 } |
439 |
459 |
440 /// \brief Notifies all the registed observers about more item erased |
460 /// \brief Notifies all the registed observers about more item erased |
441 /// from the container. |
461 /// from the container. |
442 /// |
462 /// |
443 /// It notifies all the registed observers about more item erased from |
463 /// It notifies all the registed observers about more item erased from |
444 /// the container. |
464 /// the container. |
445 /// |
465 /// |
446 void erase(const std::vector<Item>& items) { |
466 void erase(const std::vector<Item>& items) { |
447 typename Observers::iterator it; |
467 int i = 0; |
448 for (it = observers.begin(); it != observers.end(); ++it) { |
468 while (i != (int)observers.size()) { |
449 (*it)->erase(items); |
469 try { |
|
470 observers[i]->erase(items); |
|
471 ++i; |
|
472 } catch (const ImmediateDetach&) { |
|
473 observers[i]->detach(); |
|
474 } |
450 } |
475 } |
451 } |
476 } |
452 |
477 |
453 /// \brief Notifies all the registed observers about the container is |
478 /// \brief Notifies all the registed observers about the container is |
454 /// built. |
479 /// built. |
468 } |
493 } |
469 throw; |
494 throw; |
470 } |
495 } |
471 } |
496 } |
472 |
497 |
473 |
|
474 /// \brief Notifies all the registed observers about all items are |
498 /// \brief Notifies all the registed observers about all items are |
475 /// erased. |
499 /// erased. |
476 /// |
500 /// |
477 /// Notifies all the registed observers about all items are erased |
501 /// Notifies all the registed observers about all items are erased |
478 /// from the container. |
502 /// from the container. |
479 void clear() { |
503 void clear() { |
480 typename Observers::iterator it; |
504 int i = 0; |
481 for (it = observers.begin(); it != observers.end(); ++it) { |
505 while (i != (int)observers.size()) { |
482 (*it)->clear(); |
506 try { |
|
507 observers[i]->clear(); |
|
508 ++i; |
|
509 } catch (const ImmediateDetach&) { |
|
510 observers[i]->detach(); |
|
511 } |
483 } |
512 } |
484 } |
513 } |
485 }; |
514 }; |
486 |
515 |
487 } |
516 } |