COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/alteration_notifier.h @ 1134:56b07afdbf8d

Last change on this file since 1134:56b07afdbf8d was 1134:56b07afdbf8d, checked in by Balazs Dezso, 15 years ago

Documentation

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