COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/bits/alteration_notifier.h @ 1464:718207d6a1e6

Last change on this file since 1464:718207d6a1e6 was 1435:8e85e6bbefdf, checked in by Akos Ladanyi, 19 years ago

trunk/src/* move to trunk/

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