COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/bits/alteration_notifier.h @ 1359:1581f961cfaa

Last change on this file since 1359:1581f961cfaa was 1359:1581f961cfaa, checked in by Alpar Juttner, 15 years ago

Correct the english name of EGRES.

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