3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
19 #ifndef LEMON_BITS_ALTERATION_NOTIFIER_H
20 #define LEMON_BITS_ALTERATION_NOTIFIER_H
24 #include <lemon/bits/utility.h>
28 ///\brief Observer notifier for graph alteration observers.
32 /// \ingroup graphbits
34 /// \brief Notifier class to notify observes about alterations in
37 /// The simple graph's can be refered as two containers, one node container
38 /// and one edge container. But they are not standard containers they
39 /// does not store values directly they are just key continars for more
40 /// value containers which are the node and edge maps.
42 /// The graph's node and edge sets can be changed as we add or erase
43 /// nodes and edges in the graph. Lemon would like to handle easily
44 /// that the node and edge maps should contain values for all nodes or
45 /// edges. If we want to check on every indicing if the map contains
46 /// the current indicing key that cause a drawback in the performance
47 /// in the library. We use another solution we notify all maps about
48 /// an alteration in the graph, which cause only drawback on the
49 /// alteration of the graph.
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.
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.
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. The
70 /// observer base can be attached to the notifier with the
71 /// \e attach() member and can be detached with detach() function. The
72 /// alteration handlers should not call any function which signals
73 /// an other alteration in the same notifier and should not
74 /// detach any observer from the notifier.
76 /// Alteration observers try to be exception safe. If an \e add() or
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.
85 /// There are some place when the alteration observing is not completly
86 /// reliable. If we want to carry out the node degree in the graph
87 /// as in the \ref InDegMap and we use the reverseEdge that cause
88 /// unreliable functionality. Because the alteration observing signals
89 /// only erasing and adding but not the reversing it will stores bad
90 /// degrees. The sub graph adaptors cannot signal the alterations because
91 /// just a setting in the filter map can modify the graph and this cannot
92 /// be watched in any way.
94 /// \param _Container The container which is observed.
95 /// \param _Item The item type which is obserbved.
97 /// \author Balazs Dezso
99 template <typename _Container, typename _Item>
100 class AlterationNotifier {
103 typedef True Notifier;
105 typedef _Container Container;
108 /// \brief Exception which can be called from \e clear() and
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 {};
118 /// \brief ObserverBase is the base class for the observers.
120 /// ObserverBase is the abstract base class for the observers.
121 /// It will be notified about an item was inserted into or
122 /// erased from the graph.
124 /// The observer interface contains some pure virtual functions
125 /// to override. The add() and erase() functions are
126 /// to notify the oberver when one item is added or
129 /// The build() and clear() members are to notify the observer
130 /// about the container is built from an empty container or
131 /// is cleared to an empty container.
133 /// \author Balazs Dezso
137 typedef AlterationNotifier Notifier;
139 friend class AlterationNotifier;
141 /// \brief Default constructor.
143 /// Default constructor for ObserverBase.
145 ObserverBase() : notifier(0) {}
147 /// \brief Constructor which attach the observer into notifier.
149 /// Constructor which attach the observer into notifier.
150 ObserverBase(AlterationNotifier& _notifier) {
154 /// \brief Constructor which attach the obserever to the same notifier.
156 /// Constructor which attach the obserever to the same notifier as
157 /// the other observer is attached to.
158 ObserverBase(const ObserverBase& copy) {
159 if (copy.attached()) {
160 attach(*copy.getNotifier());
164 /// \brief Destructor
165 virtual ~ObserverBase() {
171 /// \brief Attaches the observer into an AlterationNotifier.
173 /// This member attaches the observer into an AlterationNotifier.
175 void attach(AlterationNotifier& _notifier) {
176 notifier = &_notifier;
177 notifier->attach(*this);
180 /// \brief Detaches the observer into an AlterationNotifier.
182 /// This member detaches the observer from an AlterationNotifier.
185 notifier->detach(*this);
188 /// \brief Gives back a pointer to the notifier which the map
191 /// This function gives back a pointer to the notifier which the map
194 Notifier* getNotifier() const { return const_cast<Notifier*>(notifier); }
196 /// Gives back true when the observer is attached into a notifier.
197 bool attached() const { return notifier != 0; }
201 ObserverBase& operator=(const ObserverBase& copy);
208 /// \brief The member function to notificate the observer about an
209 /// item is added to the container.
211 /// The add() member function notificates the observer about an item
212 /// is added to the container. It have to be overrided in the
215 virtual void add(const Item&) = 0;
217 /// \brief The member function to notificate the observer about
218 /// more item is added to the container.
220 /// The add() member function notificates the observer about more item
221 /// is added to the container. It have to be overrided in the
224 virtual void add(const std::vector<Item>& items) {
227 for (i = 0; i < (int)items.size(); ++i) {
231 for (int j = 0; j < i; ++j) {
238 /// \brief The member function to notificate the observer about an
239 /// item is erased from the container.
241 /// The erase() member function notificates the observer about an
242 /// item is erased from the container. It have to be overrided in
245 virtual void erase(const Item&) = 0;
247 /// \brief The member function to notificate the observer about
248 /// more item is erased from the container.
250 /// The erase() member function notificates the observer about more item
251 /// is erased from the container. It have to be overrided in the
253 virtual void erase(const std::vector<Item>& items) {
254 for (int i = 0; i < (int)items.size(); ++i) {
259 /// \brief The member function to notificate the observer about the
260 /// container is built.
262 /// The build() member function notificates the observer about the
263 /// container is built from an empty container. It have to be
264 /// overrided in the subclasses.
266 virtual void build() {
269 for (notifier->first(it); it != INVALID; notifier->next(it)) {
274 for (notifier->first(jt); jt != it; notifier->next(jt)) {
281 /// \brief The member function to notificate the observer about all
282 /// items are erased from the container.
284 /// The clear() member function notificates the observer about all
285 /// items are erased from the container. It have to be overrided in
287 virtual void clear() {
289 for (notifier->first(it); it != INVALID; notifier->next(it)) {
298 const Container* container;
300 typedef std::vector<ObserverBase*> Observers;
306 /// \brief Default constructor.
308 /// The default constructor of the AlterationNotifier.
309 /// It creates an empty notifier.
313 /// \brief Constructor.
315 /// Constructor with the observed container parameter.
316 AlterationNotifier(const Container& _container)
317 : container(&_container) {}
319 /// \brief Copy Constructor of the AlterationNotifier.
321 /// Copy constructor of the AlterationNotifier.
322 /// It creates only an empty notifier because the copiable
323 /// notifier's observers have to be registered still into that notifier.
324 AlterationNotifier(const AlterationNotifier& _notifier)
325 : container(_notifier.container) {}
327 /// \brief Destructor.
329 /// Destructor of the AlterationNotifier.
331 ~AlterationNotifier() {
332 typename Observers::iterator it;
333 for (it = observers.begin(); it != observers.end(); ++it) {
338 /// \brief Sets the container.
340 /// Sets the container.
341 void setContainer(const Container& _container) {
342 container = &_container;
347 AlterationNotifier& operator=(const AlterationNotifier&);
353 /// \brief First item in the container.
355 /// Returns the first item in the container. It is
356 /// for start the iteration on the container.
357 void first(Item& item) const {
358 container->first(item);
361 /// \brief Next item in the container.
363 /// Returns the next item in the container. It is
364 /// for iterate on the container.
365 void next(Item& item) const {
366 container->next(item);
369 /// \brief Returns the id of the item.
371 /// Returns the id of the item provided by the container.
372 int id(const Item& item) const {
373 return container->id(item);
376 /// \brief Returns the maximum id of the container.
378 /// Returns the maximum id of the container.
380 return container->maxId(Item());
385 void attach(ObserverBase& observer) {
386 observers.push_back(&observer);
387 observer.notifier = this;
388 observer.notifier_index = observers.size() - 1;
391 void detach(ObserverBase& observer) {
392 observers.back()->notifier_index = observer.notifier_index;
393 observers[observer.notifier_index] = observers.back();
394 observers.pop_back();
395 observer.notifier = 0;
400 /// \brief Notifies all the registed observers about an item added to
403 /// It notifies all the registed observers about an item added to
406 void add(const Item& item) {
407 typename Observers::iterator it;
409 for (it = observers.begin(); it != observers.end(); ++it) {
413 typename Observers::iterator jt;
414 for (jt = observers.begin(); jt != it; ++jt) {
421 /// \brief Notifies all the registed observers about more item added to
424 /// It notifies all the registed observers about more item added to
427 void add(const std::vector<Item>& items) {
428 typename Observers::iterator it;
430 for (it = observers.begin(); it != observers.end(); ++it) {
434 typename Observers::iterator jt;
435 for (jt = observers.begin(); jt != it; ++jt) {
442 /// \brief Notifies all the registed observers about an item erased from
445 /// It notifies all the registed observers about an item erased from
448 void erase(const Item& key) throw() {
450 while (i != (int)observers.size()) {
452 observers[i]->erase(key);
454 } catch (const ImmediateDetach&) {
455 observers[i]->detach();
460 /// \brief Notifies all the registed observers about more item erased
461 /// from the container.
463 /// It notifies all the registed observers about more item erased from
466 void erase(const std::vector<Item>& items) {
468 while (i != (int)observers.size()) {
470 observers[i]->erase(items);
472 } catch (const ImmediateDetach&) {
473 observers[i]->detach();
478 /// \brief Notifies all the registed observers about the container is
481 /// Notifies all the registed observers about the container is built
482 /// from an empty container.
484 typename Observers::iterator it;
486 for (it = observers.begin(); it != observers.end(); ++it) {
490 typename Observers::iterator jt;
491 for (jt = observers.begin(); jt != it; ++jt) {
498 /// \brief Notifies all the registed observers about all items are
501 /// Notifies all the registed observers about all items are erased
502 /// from the container.
505 while (i != (int)observers.size()) {
507 observers[i]->clear();
509 } catch (const ImmediateDetach&) {
510 observers[i]->detach();