COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/bits/alteration_notifier.h @ 1685:5b37a10234bc

Last change on this file since 1685:5b37a10234bc was 1685:5b37a10234bc, checked in by Balazs Dezso, 19 years ago

Some bugfixes

File size: 12.1 KB
RevLine 
[946]1/* -*- C++ -*-
[1435]2 * lemon/notifier.h - Part of LEMON, a generic C++ optimization library
[946]3 *
[1164]4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
[1359]5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
[946]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
[1587]23///\ingroup graphmapfactory
[946]24///\file
25///\brief Observer registry for graph alteration observers.
26
27namespace lemon {
28
[1587]29  /// \addtogroup graphmapfactory
[946]30  /// @{
31
[1414]32  /// \brief Registry class to register objects observes alterations in
33  /// the graph.
34  ///
[946]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
[1038]38  /// from the \ref AlterationNotifier::ObserverBase and override
[946]39  /// the virtual functions in that.
40  ///
41  /// The most important application of the alteration observing is the
[1414]42  /// dynamic map implementation.
[946]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>
[1038]50  class AlterationNotifier {
[946]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
[1204]66    /// about the container is built from an empty container or
[946]67    /// is cleared to an empty container.
68    ///
69    /// \author Balazs Dezso
70
71    class ObserverBase {
72    protected:
[1038]73      typedef AlterationNotifier Registry;
[946]74
[1038]75      friend class AlterationNotifier;
[946]76
[1414]77      /// \brief Default constructor.
78      ///
[946]79      /// Default constructor for ObserverBase.
80      ///
81      ObserverBase() : registry(0) {}
82
[1685]83      ObserverBase(const ObserverBase& copy) {
84        if (copy.attached()) {
85          copy.getRegistry()->attach(*this);
86        }
87      }
88       
[946]89      virtual ~ObserverBase() {}
90
[1414]91      /// \brief Attaches the observer into an AlterationNotifier.
92      ///
[1038]93      /// This member attaches the observer into an AlterationNotifier.
[946]94      ///
[1038]95      void attach(AlterationNotifier& r) {
[946]96        registry = &r;
97        registry->attach(*this);
98      }
99
[1414]100      /// \brief Detaches the observer into an AlterationNotifier.
101      ///
[1038]102      /// This member detaches the observer from an AlterationNotifier.
[946]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; }
[1685]120
[946]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       
[1414]139      virtual void add(const Item&) = 0;
[946]140
[1414]141      /// \brief The member function to notificate the observer about
142      /// simulitem is added to the container.
143      ///
144      /// The add() member function notificates the observer about an 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      }
[946]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
[1414]163      virtual void erase(const std::vector<Item>& items) {
164        for (int i = 0; i < (int)items.size(); ++i) {
165          add(items[i]);
166        }
167      }
168
[946]169      /// \brief The member function to notificate the observer about the
[1204]170      /// container is built.
[946]171      ///
172      /// The build() member function notificates the observer about the
[1204]173      /// container is built from an empty container. It have to be
[946]174      /// overrided in the subclasses.
175
176      virtual void build() = 0;
177
178      /// \brief The member function to notificate the observer about all
179      /// items are erased from the container.
180      ///
181      /// The clear() member function notificates the observer about all
182      /// items are erased from the container. It have to be overrided in
183      /// the subclasses.
184     
185      virtual void clear() = 0;
186
187    };
188       
189  protected:
190       
191
192    typedef std::vector<ObserverBase*> Container;
193
194    Container container;
195
196               
197  public:
198
199    /// Default constructor.
200       
201    ///
[1038]202    /// The default constructor of the AlterationNotifier.
[946]203    /// It creates an empty registry.
[1038]204    AlterationNotifier() {}
[946]205
[1038]206    /// Copy Constructor of the AlterationNotifier.
[946]207       
[1038]208    /// Copy constructor of the AlterationNotifier.
[946]209    /// It creates only an empty registry because the copiable
210    /// registry's observers have to be registered still into that registry.
[1039]211    AlterationNotifier(const AlterationNotifier&) {}
[946]212
213    /// Assign operator.
214               
[1038]215    /// Assign operator for the AlterationNotifier.
[1040]216    /// It makes the notifier only empty because the copiable
217    /// notifier's observers have to be registered still into that registry.
[1039]218    AlterationNotifier& operator=(const AlterationNotifier&) {
[946]219      typename Container::iterator it;
220      for (it = container.begin(); it != container.end(); ++it) {
221        (*it)->registry = 0;
222      }
223    }
224
225    /// Destructor.
226                               
[1038]227    /// Destructor of the AlterationNotifier.
[946]228    ///
[1038]229    ~AlterationNotifier() {
[946]230      typename Container::iterator it;
231      for (it = container.begin(); it != container.end(); ++it) {
232        (*it)->registry = 0;
233      }
234    }
235       
236       
237  protected:
238
239    void attach(ObserverBase& observer) {
240      container.push_back(&observer);
241      observer.registry = this;
242      observer.registry_index = container.size()-1;
243    }
244
245    void detach(ObserverBase& base) {
246      container.back()->registry_index = base.registry_index;
247      container[base.registry_index] = container.back();
248      container.pop_back();
249      base.registry = 0;
250    }
251
252  public:
253       
[1414]254    /// \brief Notifies all the registered observers about an Item added to
255    /// the container.
256    ///
257    /// It notifies all the registered observers about an Item added to
258    /// the container.
[946]259    ///
[1414]260    void add(const Item& item) {
[946]261      typename Container::iterator it;
262      for (it = container.begin(); it != container.end(); ++it) {
[1414]263        (*it)->add(item);
[946]264      }
265    }   
266
[1414]267    /// \brief Notifies all the registered observers about more Item added to
268    /// the container.
269    ///
270    /// It notifies all the registered observers about more Item added to
271    /// the container.
272    ///
273    void add(const std::vector<Item>& items) {
274      typename Container::iterator it;
275      for (it = container.begin(); it != container.end(); ++it) {
276        (*it)->add(items);
277      }
278    }   
279
280    /// \brief Notifies all the registered observers about an Item erased from
281    /// the container.
282    ///
283    /// It notifies all the registered observers about an Item erased from
284    /// the container.
[946]285    ///
286    void erase(const Item& key) {
287      typename Container::iterator it;
288      for (it = container.begin(); it != container.end(); ++it) {
289        (*it)->erase(key);
290      }
291    }
[1414]292
293    /// \brief Notifies all the registered observers about more Item erased 
294    /// from the container.
295    ///
296    /// It notifies all the registered observers about more Item erased from
297    /// the container.
298    ///
299    void erase(const std::vector<Item>& items) {
300      typename Container::iterator it;
301      for (it = container.begin(); it != container.end(); ++it) {
302        (*it)->erase(items);
303      }
304    }
[946]305   
306
[1414]307    /// \brief Notifies all the registered observers about the container is
308    /// built.
309    ///         
[1204]310    /// Notifies all the registered observers about the container is built
[946]311    /// from an empty container.
312    void build() {
313      typename Container::iterator it;
314      for (it = container.begin(); it != container.end(); ++it) {
315        (*it)->build();
316      }
317    }
318
319
[1414]320    /// \brief Notifies all the registered observers about all Items are
321    /// erased.
322    ///
[946]323    /// Notifies all the registered observers about all Items are erased
324    /// from the container.
325    void clear() {
326      typename Container::iterator it;
327      for (it = container.begin(); it != container.end(); ++it) {
328        (*it)->clear();
329      }
330    }
331  };
332
333
[962]334  /// \brief Class to extend a graph with the functionality of alteration
335  /// observing.
336  ///
337  /// AlterableGraphExtender extends the _Base graphs functionality with
338  /// the possibility of alteration observing. It defines two observer
339  /// registrys for the nodes and mapes.
340  ///
341  /// \todo Document what "alteration observing" is. And probably find a
342  /// better (shorter) name.
[946]343  ///
344  /// \param _Base is the base class to extend.
345  ///
346  /// \pre _Base is conform to the BaseGraphComponent concept.
347  ///
[962]348  /// \post AlterableGraphExtender<_Base> is conform to the
349  /// AlterableGraphComponent concept.
[946]350  ///
351  /// \author Balazs Dezso
352
353  template <typename _Base>
354  class AlterableGraphExtender : public _Base {
355  public:
356
357    typedef AlterableGraphExtender Graph;
358    typedef _Base Parent;
359
360    typedef typename Parent::Node Node;
361    typedef typename Parent::Edge Edge;
362
[962]363    /// The edge observer registry.
[1039]364    typedef AlterationNotifier<Edge> EdgeNotifier;
[946]365    /// The node observer registry.
[1039]366    typedef AlterationNotifier<Node> NodeNotifier;
[946]367
368
369  protected:
370
[1040]371    mutable EdgeNotifier edge_notifier;
[946]372
[1040]373    mutable NodeNotifier node_notifier;
[946]374
375  public:
376
[1134]377    /// \brief Gives back the edge alteration notifier.
378    ///
379    /// Gives back the edge alteration notifier.
380    EdgeNotifier& getNotifier(Edge) const {
[1040]381      return edge_notifier;
[946]382    }
383
[1134]384    /// \brief Gives back the node alteration notifier.
385    ///
386    /// Gives back the node alteration notifier.
387    NodeNotifier& getNotifier(Node) const {
[1040]388      return node_notifier;
[946]389    }
390
391    ~AlterableGraphExtender() {
[1040]392      node_notifier.clear();
393      edge_notifier.clear();
[946]394    }
395   
396  };
397
[962]398  /// \brief Class to extend an undirected graph with the functionality of
399  /// alteration observing.
400  ///
401  /// \todo Document.
402  ///
403  /// \sa AlterableGraphExtender
404  ///
405  /// \bug This should be done some other way. Possibilities: template
406  /// specialization (not very easy, if at all possible); some kind of
407  /// enable_if boost technique?
408
409  template <typename _Base>
410  class AlterableUndirGraphExtender
411    : public AlterableGraphExtender<_Base> {
412  public:
413
414    typedef AlterableUndirGraphExtender Graph;
415    typedef AlterableGraphExtender<_Base> Parent;
416
417    typedef typename Parent::UndirEdge UndirEdge;
418
419    /// The edge observer registry.
[1039]420    typedef AlterationNotifier<UndirEdge> UndirEdgeNotifier;
[962]421
422  protected:
423
[1040]424    mutable UndirEdgeNotifier undir_edge_notifier;
[962]425
[1022]426  public:
427
[1038]428    using Parent::getNotifier;
[1039]429    UndirEdgeNotifier& getNotifier(UndirEdge) const {
[1040]430      return undir_edge_notifier;
[962]431    }
432
433    ~AlterableUndirGraphExtender() {
[1040]434      undir_edge_notifier.clear();
[962]435    }
436  };
[946]437 
438/// @}
439 
440
441}
442
443#endif
Note: See TracBrowser for help on using the repository browser.