47 /// the current indicing key that cause a drawback in the performance |
47 /// the current indicing key that cause a drawback in the performance |
48 /// in the library. We use another solution we notify all maps about |
48 /// in the library. We use another solution we notify all maps about |
49 /// an alteration in the graph, which cause only drawback on the |
49 /// an alteration in the graph, which cause only drawback on the |
50 /// alteration of the graph. |
50 /// alteration of the graph. |
51 /// |
51 /// |
52 /// This class provides an interface to the container. The \e first() and \e |
52 /// This class provides an interface to the container. The \e first() and \e |
53 /// next() member functions make possible to iterate on the keys of the |
53 /// next() member functions make possible to iterate on the keys of the |
54 /// container. The \e id() function returns an integer id for each key. |
54 /// container. The \e id() function returns an integer id for each key. |
55 /// The \e maxId() function gives back an upper bound of the ids. |
55 /// The \e maxId() function gives back an upper bound of the ids. |
56 /// |
56 /// |
57 /// For the proper functonality of this class, we should notify it |
57 /// For the proper functonality of this class, we should notify it |
58 /// about each alteration in the container. The alterations have four type |
58 /// about each alteration in the container. The alterations have four type |
59 /// as \e add(), \e erase(), \e build() and \e clear(). The \e add() and |
59 /// as \e add(), \e erase(), \e build() and \e clear(). The \e add() and |
60 /// \e erase() signals that only one or few items added or erased to or |
60 /// \e erase() signals that only one or few items added or erased to or |
61 /// from the graph. If all items are erased from the graph or from an empty |
61 /// from the graph. If all items are erased from the graph or from an empty |
62 /// graph a new graph is builded then it can be signaled with the |
62 /// graph a new graph is builded then it can be signaled with the |
63 /// clear() and build() members. Important rule that if we erase items |
63 /// clear() and build() members. Important rule that if we erase items |
64 /// from graph we should first signal the alteration and after that erase |
64 /// from graph we should first signal the alteration and after that erase |
65 /// them from the container, on the other way on item addition we should |
65 /// them from the container, on the other way on item addition we should |
66 /// first extend the container and just after that signal the alteration. |
66 /// first extend the container and just after that signal the alteration. |
67 /// |
67 /// |
68 /// The alteration can be observed with a class inherited from the |
68 /// The alteration can be observed with a class inherited from the |
69 /// \e ObserverBase nested class. The signals can be handled with |
69 /// \e ObserverBase nested class. The signals can be handled with |
70 /// overriding the virtual functions defined in the base class. The |
70 /// overriding the virtual functions defined in the base class. The |
71 /// observer base can be attached to the notifier with the |
71 /// observer base can be attached to the notifier with the |
72 /// \e attach() member and can be detached with detach() function. The |
72 /// \e attach() member and can be detached with detach() function. The |
73 /// alteration handlers should not call any function which signals |
73 /// alteration handlers should not call any function which signals |
74 /// an other alteration in the same notifier and should not |
74 /// an other alteration in the same notifier and should not |
75 /// detach any observer from the notifier. |
75 /// detach any observer from the notifier. |
76 /// |
76 /// |
77 /// Alteration observers try to be exception safe. If an \e add() or |
77 /// Alteration observers try to be exception safe. If an \e add() or |
78 /// a \e clear() function throws an exception then the remaining |
78 /// a \e clear() function throws an exception then the remaining |
79 /// observeres will not be notified and the fulfilled additions will |
79 /// observeres will not be notified and the fulfilled additions will |
80 /// be rolled back by calling the \e erase() or \e clear() |
80 /// be rolled back by calling the \e erase() or \e clear() |
81 /// functions. Thence the \e erase() and \e clear() should not throw |
81 /// functions. Thence the \e erase() and \e clear() should not throw |
82 /// exception. Actullay, it can be throw only |
82 /// exception. Actullay, it can be throw only |
83 /// \ref AlterationObserver::ImmediateDetach ImmediateDetach |
83 /// \ref AlterationObserver::ImmediateDetach ImmediateDetach |
84 /// exception which detach the observer from the notifier. |
84 /// exception which detach the observer from the notifier. |
85 /// |
85 /// |
86 /// There are some place when the alteration observing is not completly |
86 /// There are some place when the alteration observing is not completly |
87 /// reliable. If we want to carry out the node degree in the graph |
87 /// reliable. If we want to carry out the node degree in the graph |
88 /// as in the \ref InDegMap and we use the reverseEdge that cause |
88 /// as in the \ref InDegMap and we use the reverseEdge that cause |
89 /// unreliable functionality. Because the alteration observing signals |
89 /// unreliable functionality. Because the alteration observing signals |
90 /// only erasing and adding but not the reversing it will stores bad |
90 /// only erasing and adding but not the reversing it will stores bad |
91 /// degrees. The sub graph adaptors cannot signal the alterations because |
91 /// degrees. The sub graph adaptors cannot signal the alterations because |
92 /// just a setting in the filter map can modify the graph and this cannot |
92 /// just a setting in the filter map can modify the graph and this cannot |
93 /// be watched in any way. |
93 /// be watched in any way. |
125 /// to notify the oberver when one item is added or |
125 /// to notify the oberver when one item is added or |
126 /// erased. |
126 /// erased. |
127 /// |
127 /// |
128 /// The build() and clear() members are to notify the observer |
128 /// The build() and clear() members are to notify the observer |
129 /// about the container is built from an empty container or |
129 /// about the container is built from an empty container or |
130 /// is cleared to an empty container. |
130 /// is cleared to an empty container. |
131 |
131 |
132 class ObserverBase { |
132 class ObserverBase { |
133 protected: |
133 protected: |
134 typedef AlterationNotifier Notifier; |
134 typedef AlterationNotifier Notifier; |
135 |
135 |
136 friend class AlterationNotifier; |
136 friend class AlterationNotifier; |
137 |
137 |
138 /// \brief Default constructor. |
138 /// \brief Default constructor. |
139 /// |
139 /// |
140 /// Default constructor for ObserverBase. |
140 /// Default constructor for ObserverBase. |
141 /// |
141 /// |
142 ObserverBase() : _notifier(0) {} |
142 ObserverBase() : _notifier(0) {} |
143 |
143 |
144 /// \brief Constructor which attach the observer into notifier. |
144 /// \brief Constructor which attach the observer into notifier. |
145 /// |
145 /// |
146 /// Constructor which attach the observer into notifier. |
146 /// Constructor which attach the observer into notifier. |
168 /// \brief Attaches the observer into an AlterationNotifier. |
168 /// \brief Attaches the observer into an AlterationNotifier. |
169 /// |
169 /// |
170 /// This member attaches the observer into an AlterationNotifier. |
170 /// This member attaches the observer into an AlterationNotifier. |
171 /// |
171 /// |
172 void attach(AlterationNotifier& nf) { |
172 void attach(AlterationNotifier& nf) { |
173 nf.attach(*this); |
173 nf.attach(*this); |
174 } |
174 } |
175 |
175 |
176 /// \brief Detaches the observer into an AlterationNotifier. |
176 /// \brief Detaches the observer into an AlterationNotifier. |
177 /// |
177 /// |
178 /// This member detaches the observer from an AlterationNotifier. |
178 /// This member detaches the observer from an AlterationNotifier. |
179 /// |
179 /// |
180 void detach() { |
180 void detach() { |
181 _notifier->detach(*this); |
181 _notifier->detach(*this); |
182 } |
182 } |
183 |
183 |
184 /// \brief Gives back a pointer to the notifier which the map |
184 /// \brief Gives back a pointer to the notifier which the map |
185 /// attached into. |
185 /// attached into. |
186 /// |
186 /// |
187 /// This function gives back a pointer to the notifier which the map |
187 /// This function gives back a pointer to the notifier which the map |
188 /// attached into. |
188 /// attached into. |
189 /// |
189 /// |
190 Notifier* notifier() const { return const_cast<Notifier*>(_notifier); } |
190 Notifier* notifier() const { return const_cast<Notifier*>(_notifier); } |
191 |
191 |
192 /// Gives back true when the observer is attached into a notifier. |
192 /// Gives back true when the observer is attached into a notifier. |
193 bool attached() const { return _notifier != 0; } |
193 bool attached() const { return _notifier != 0; } |
194 |
194 |
195 private: |
195 private: |
196 |
196 |
197 ObserverBase& operator=(const ObserverBase& copy); |
197 ObserverBase& operator=(const ObserverBase& copy); |
198 |
198 |
199 protected: |
199 protected: |
200 |
200 |
201 Notifier* _notifier; |
201 Notifier* _notifier; |
202 typename std::list<ObserverBase*>::iterator _index; |
202 typename std::list<ObserverBase*>::iterator _index; |
203 |
203 |
204 /// \brief The member function to notificate the observer about an |
204 /// \brief The member function to notificate the observer about an |
205 /// item is added to the container. |
205 /// item is added to the container. |
245 /// \brief The member function to notificate the observer about all |
245 /// \brief The member function to notificate the observer about all |
246 /// items are erased from the container. |
246 /// items are erased from the container. |
247 /// |
247 /// |
248 /// The clear() member function notificates the observer about all |
248 /// The clear() member function notificates the observer about all |
249 /// items are erased from the container. It have to be overrided in |
249 /// items are erased from the container. It have to be overrided in |
250 /// the subclasses. |
250 /// the subclasses. |
251 virtual void clear() = 0; |
251 virtual void clear() = 0; |
252 |
252 |
253 }; |
253 }; |
254 |
254 |
255 protected: |
255 protected: |
256 |
256 |
257 const Container* container; |
257 const Container* container; |
258 |
258 |
259 typedef std::list<ObserverBase*> Observers; |
259 typedef std::list<ObserverBase*> Observers; |
260 Observers _observers; |
260 Observers _observers; |
261 |
261 |
262 |
262 |
263 public: |
263 public: |
264 |
264 |
265 /// \brief Default constructor. |
265 /// \brief Default constructor. |
266 /// |
266 /// |
267 /// The default constructor of the AlterationNotifier. |
267 /// The default constructor of the AlterationNotifier. |
268 /// It creates an empty notifier. |
268 /// It creates an empty notifier. |
269 AlterationNotifier() |
269 AlterationNotifier() |
270 : container(0) {} |
270 : container(0) {} |
271 |
271 |
272 /// \brief Constructor. |
272 /// \brief Constructor. |
273 /// |
273 /// |
274 /// Constructor with the observed container parameter. |
274 /// Constructor with the observed container parameter. |
275 AlterationNotifier(const Container& _container) |
275 AlterationNotifier(const Container& _container) |
276 : container(&_container) {} |
276 : container(&_container) {} |
277 |
277 |
278 /// \brief Copy Constructor of the AlterationNotifier. |
278 /// \brief Copy Constructor of the AlterationNotifier. |
279 /// |
279 /// |
280 /// Copy constructor of the AlterationNotifier. |
280 /// Copy constructor of the AlterationNotifier. |
281 /// It creates only an empty notifier because the copiable |
281 /// It creates only an empty notifier because the copiable |
282 /// notifier's observers have to be registered still into that notifier. |
282 /// notifier's observers have to be registered still into that notifier. |
283 AlterationNotifier(const AlterationNotifier& _notifier) |
283 AlterationNotifier(const AlterationNotifier& _notifier) |
284 : container(_notifier.container) {} |
284 : container(_notifier.container) {} |
285 |
285 |
286 /// \brief Destructor. |
286 /// \brief Destructor. |
287 /// |
287 /// |
288 /// Destructor of the AlterationNotifier. |
288 /// Destructor of the AlterationNotifier. |
289 /// |
289 /// |
290 ~AlterationNotifier() { |
290 ~AlterationNotifier() { |
291 typename Observers::iterator it; |
291 typename Observers::iterator it; |
292 for (it = _observers.begin(); it != _observers.end(); ++it) { |
292 for (it = _observers.begin(); it != _observers.end(); ++it) { |
293 (*it)->_notifier = 0; |
293 (*it)->_notifier = 0; |
294 } |
294 } |
295 } |
295 } |
296 |
296 |
297 /// \brief Sets the container. |
297 /// \brief Sets the container. |
298 /// |
298 /// |
336 /// |
336 /// |
337 /// Returns the maximum id of the container. |
337 /// Returns the maximum id of the container. |
338 int maxId() const { |
338 int maxId() const { |
339 return container->maxId(Item()); |
339 return container->maxId(Item()); |
340 } |
340 } |
341 |
341 |
342 protected: |
342 protected: |
343 |
343 |
344 void attach(ObserverBase& observer) { |
344 void attach(ObserverBase& observer) { |
345 observer._index = _observers.insert(_observers.begin(), &observer); |
345 observer._index = _observers.insert(_observers.begin(), &observer); |
346 observer._notifier = this; |
346 observer._notifier = this; |
347 } |
347 } |
348 |
348 |
349 void detach(ObserverBase& observer) { |
349 void detach(ObserverBase& observer) { |
350 _observers.erase(observer._index); |
350 _observers.erase(observer._index); |
351 observer._index = _observers.end(); |
351 observer._index = _observers.end(); |
352 observer._notifier = 0; |
352 observer._notifier = 0; |
353 } |
353 } |
354 |
354 |
355 public: |
355 public: |
356 |
356 |
357 /// \brief Notifies all the registed observers about an item added to |
357 /// \brief Notifies all the registed observers about an item added to |
358 /// the container. |
358 /// the container. |
359 /// |
359 /// |
360 /// It notifies all the registed observers about an item added to |
360 /// It notifies all the registed observers about an item added to |
361 /// the container. |
361 /// the container. |
362 /// |
362 /// |
363 void add(const Item& item) { |
363 void add(const Item& item) { |
364 typename Observers::reverse_iterator it; |
364 typename Observers::reverse_iterator it; |
365 try { |
365 try { |
366 for (it = _observers.rbegin(); it != _observers.rend(); ++it) { |
366 for (it = _observers.rbegin(); it != _observers.rend(); ++it) { |
367 (*it)->add(item); |
367 (*it)->add(item); |