COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/bits/alteration_notifier.h @ 1729:06f939455cb1

Last change on this file since 1729:06f939455cb1 was 1729:06f939455cb1, checked in by Balazs Dezso, 14 years ago

Removing signal/commit Change from alteration notifier

It makes slower the change Target/Source? functions
and used only by the In/Out? DegMap?

File size: 12.4 KB
Line 
1/* -*- C++ -*-
2 * 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 graphmapfactory
24///\file
25///\brief Observer registry for graph alteration observers.
26
27namespace lemon {
28
29  /// \addtogroup graphmapfactory
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      ObserverBase(const ObserverBase& copy) {
84        if (copy.attached()) {
85          copy.getRegistry()->attach(*this);
86        }
87      }
88       
89      virtual ~ObserverBase() {}
90
91      /// \brief Attaches the observer into an AlterationNotifier.
92      ///
93      /// This member attaches the observer into an AlterationNotifier.
94      ///
95      void attach(AlterationNotifier& r) {
96        registry = &r;
97        registry->attach(*this);
98      }
99
100      /// \brief Detaches the observer into an AlterationNotifier.
101      ///
102      /// This member detaches the observer from an AlterationNotifier.
103      ///
104      void detach() {
105        if (registry) {
106          registry->detach(*this);
107        }
108      }
109       
110
111      /// Gives back a pointer to the registry what the map attached into.
112
113      /// This function gives back a pointer to the registry what the map
114      /// attached into.
115      ///
116      Registry* getRegistry() const { return const_cast<Registry*>(registry); }
117     
118      /// Gives back true when the observer is attached into a registry.
119      bool attached() const { return registry != 0; }
120
121    private:
122
123      ObserverBase& operator=(const ObserverBase& copy);
124
125    protected:
126     
127      Registry* registry;
128      int registry_index;
129
130    public:
131
132      /// \brief The member function to notificate the observer about an
133      /// item is added to the container.
134      ///
135      /// The add() member function notificates the observer about an item
136      /// is added to the container. It have to be overrided in the
137      /// subclasses.
138       
139      virtual void add(const Item&) = 0;
140
141      /// \brief The member function to notificate the observer about
142      /// more item is added to the container.
143      ///
144      /// The add() member function notificates the observer about more item
145      /// is added to the container. It have to be overrided in the
146      /// subclasses.
147
148      virtual void add(const std::vector<Item>& items) {
149        for (int i = 0; i < (int)items.size(); ++i) {
150          add(items[i]);
151        }
152      }
153
154      /// \brief The member function to notificate the observer about an
155      /// item is erased from the container.
156      ///
157      /// The erase() member function notificates the observer about an
158      /// item is erased from the container. It have to be overrided in
159      /// the subclasses.
160       
161      virtual void erase(const Item&) = 0;
162
163      /// \brief The member function to notificate the observer about
164      /// more item is erased from the container.
165      ///
166      /// The erase() member function notificates the observer about more item
167      /// is erased from the container. It have to be overrided in the
168      /// subclasses.
169      virtual void erase(const std::vector<Item>& items) {
170        for (int i = 0; i < (int)items.size(); ++i) {
171          erase(items[i]);
172        }
173      }
174
175      /// \brief The member function to notificate the observer about the
176      /// container is built.
177      ///
178      /// The build() member function notificates the observer about the
179      /// container is built from an empty container. It have to be
180      /// overrided in the subclasses.
181
182      virtual void build() = 0;
183
184      /// \brief The member function to notificate the observer about all
185      /// items are erased from the container.
186      ///
187      /// The clear() member function notificates the observer about all
188      /// items are erased from the container. It have to be overrided in
189      /// the subclasses.
190     
191      virtual void clear() = 0;
192
193    };
194       
195  protected:
196       
197
198    typedef std::vector<ObserverBase*> Container;
199
200    Container container;
201
202               
203  public:
204
205    /// Default constructor.
206       
207    ///
208    /// The default constructor of the AlterationNotifier.
209    /// It creates an empty registry.
210    AlterationNotifier() {}
211
212    /// Copy Constructor of the AlterationNotifier.
213       
214    /// Copy constructor of the AlterationNotifier.
215    /// It creates only an empty registry because the copiable
216    /// registry's observers have to be registered still into that registry.
217    AlterationNotifier(const AlterationNotifier&) {}
218
219    /// Assign operator.
220               
221    /// Assign operator for the AlterationNotifier.
222    /// It makes the notifier only empty because the copiable
223    /// notifier's observers have to be registered still into that registry.
224    AlterationNotifier& operator=(const AlterationNotifier&) {
225      typename Container::iterator it;
226      for (it = container.begin(); it != container.end(); ++it) {
227        (*it)->registry = 0;
228      }
229    }
230
231    /// Destructor.
232                               
233    /// Destructor of the AlterationNotifier.
234    ///
235    ~AlterationNotifier() {
236      typename Container::iterator it;
237      for (it = container.begin(); it != container.end(); ++it) {
238        (*it)->registry = 0;
239      }
240    }
241       
242       
243  protected:
244
245    void attach(ObserverBase& observer) {
246      container.push_back(&observer);
247      observer.registry = this;
248      observer.registry_index = container.size()-1;
249    }
250
251    void detach(ObserverBase& base) {
252      container.back()->registry_index = base.registry_index;
253      container[base.registry_index] = container.back();
254      container.pop_back();
255      base.registry = 0;
256    }
257
258  public:
259       
260    /// \brief Notifies all the registered observers about an Item added to
261    /// the container.
262    ///
263    /// It notifies all the registered observers about an Item added to
264    /// the container.
265    ///
266    void add(const Item& item) {
267      typename Container::iterator it;
268      for (it = container.begin(); it != container.end(); ++it) {
269        (*it)->add(item);
270      }
271    }   
272
273    /// \brief Notifies all the registered observers about more Item added to
274    /// the container.
275    ///
276    /// It notifies all the registered observers about more Item added to
277    /// the container.
278    ///
279    void add(const std::vector<Item>& items) {
280      typename Container::iterator it;
281      for (it = container.begin(); it != container.end(); ++it) {
282        (*it)->add(items);
283      }
284    }   
285
286    /// \brief Notifies all the registered observers about an Item erased from
287    /// the container.
288    ///
289    /// It notifies all the registered observers about an Item erased from
290    /// the container.
291    ///
292    void erase(const Item& key) {
293      typename Container::iterator it;
294      for (it = container.begin(); it != container.end(); ++it) {
295        (*it)->erase(key);
296      }
297    }
298
299    /// \brief Notifies all the registered observers about more Item erased 
300    /// from the container.
301    ///
302    /// It notifies all the registered observers about more Item erased from
303    /// the container.
304    ///
305    void erase(const std::vector<Item>& items) {
306      typename Container::iterator it;
307      for (it = container.begin(); it != container.end(); ++it) {
308        (*it)->erase(items);
309      }
310    }
311
312    /// \brief Notifies all the registered observers about the container is
313    /// built.
314    ///         
315    /// Notifies all the registered observers about the container is built
316    /// from an empty container.
317    void build() {
318      typename Container::iterator it;
319      for (it = container.begin(); it != container.end(); ++it) {
320        (*it)->build();
321      }
322    }
323
324
325    /// \brief Notifies all the registered observers about all Items are
326    /// erased.
327    ///
328    /// Notifies all the registered observers about all Items are erased
329    /// from the container.
330    void clear() {
331      typename Container::iterator it;
332      for (it = container.begin(); it != container.end(); ++it) {
333        (*it)->clear();
334      }
335    }
336  };
337
338
339  /// \brief Class to extend a graph with the functionality of alteration
340  /// observing.
341  ///
342  /// AlterableGraphExtender extends the _Base graphs functionality with
343  /// the possibility of alteration observing. It defines two observer
344  /// registrys for the nodes and mapes.
345  ///
346  /// \todo Document what "alteration observing" is. And probably find a
347  /// better (shorter) name.
348  ///
349  /// \param _Base is the base class to extend.
350  ///
351  /// \pre _Base is conform to the BaseGraphComponent concept.
352  ///
353  /// \post AlterableGraphExtender<_Base> is conform to the
354  /// AlterableGraphComponent concept.
355  ///
356  /// \author Balazs Dezso
357
358  template <typename _Base>
359  class AlterableGraphExtender : public _Base {
360  public:
361
362    typedef AlterableGraphExtender Graph;
363    typedef _Base Parent;
364
365    typedef typename Parent::Node Node;
366    typedef typename Parent::Edge Edge;
367
368    /// The edge observer registry.
369    typedef AlterationNotifier<Edge> EdgeNotifier;
370    /// The node observer registry.
371    typedef AlterationNotifier<Node> NodeNotifier;
372
373
374  protected:
375
376    mutable EdgeNotifier edge_notifier;
377
378    mutable NodeNotifier node_notifier;
379
380  public:
381
382    /// \brief Gives back the edge alteration notifier.
383    ///
384    /// Gives back the edge alteration notifier.
385    EdgeNotifier& getNotifier(Edge) const {
386      return edge_notifier;
387    }
388
389    /// \brief Gives back the node alteration notifier.
390    ///
391    /// Gives back the node alteration notifier.
392    NodeNotifier& getNotifier(Node) const {
393      return node_notifier;
394    }
395
396    ~AlterableGraphExtender() {
397      node_notifier.clear();
398      edge_notifier.clear();
399    }
400   
401  };
402
403  /// \brief Class to extend an undirected graph with the functionality of
404  /// alteration observing.
405  ///
406  /// \todo Document.
407  ///
408  /// \sa AlterableGraphExtender
409  ///
410  /// \bug This should be done some other way. Possibilities: template
411  /// specialization (not very easy, if at all possible); some kind of
412  /// enable_if boost technique?
413
414  template <typename _Base>
415  class AlterableUndirGraphExtender
416    : public AlterableGraphExtender<_Base> {
417  public:
418
419    typedef AlterableUndirGraphExtender Graph;
420    typedef AlterableGraphExtender<_Base> Parent;
421
422    typedef typename Parent::UndirEdge UndirEdge;
423
424    /// The edge observer registry.
425    typedef AlterationNotifier<UndirEdge> UndirEdgeNotifier;
426
427  protected:
428
429    mutable UndirEdgeNotifier undir_edge_notifier;
430
431  public:
432
433    using Parent::getNotifier;
434    UndirEdgeNotifier& getNotifier(UndirEdge) const {
435      return undir_edge_notifier;
436    }
437
438    ~AlterableUndirGraphExtender() {
439      undir_edge_notifier.clear();
440    }
441  };
442 
443/// @}
444 
445
446}
447
448#endif
Note: See TracBrowser for help on using the repository browser.