COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/bits/alteration_notifier.h @ 1910:f95eea8c34b0

Last change on this file since 1910:f95eea8c34b0 was 1910:f95eea8c34b0, checked in by Balazs Dezso, 18 years ago

Bipartite => Bp
Upper => A
Lower => B

+ some bug fix

File size: 14.9 KB
RevLine 
[946]1/* -*- C++ -*-
[1435]2 * lemon/notifier.h - Part of LEMON, a generic C++ optimization library
[946]3 *
[1875]4 * Copyright (C) 2006 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
[1910]5 * (Egervary Research Groin 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
[1910]23///\ingroin graphmapfactory
[946]24///\file
25///\brief Observer registry for graph alteration observers.
26
27namespace lemon {
28
[1910]29  /// \addtogroin 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      /// \brief The member function to notificate the observer about an
131      /// item is added to the container.
132      ///
133      /// The add() member function notificates the observer about an item
134      /// is added to the container. It have to be overrided in the
135      /// subclasses.
136       
[1414]137      virtual void add(const Item&) = 0;
[946]138
[1414]139      /// \brief The member function to notificate the observer about
[1718]140      /// more item is added to the container.
[1414]141      ///
[1718]142      /// The add() member function notificates the observer about more item
[1414]143      /// is added to the container. It have to be overrided in the
144      /// subclasses.
145
146      virtual void add(const std::vector<Item>& items) {
147        for (int i = 0; i < (int)items.size(); ++i) {
148          add(items[i]);
149        }
150      }
[946]151
152      /// \brief The member function to notificate the observer about an
153      /// item is erased from the container.
154      ///
155      /// The erase() member function notificates the observer about an
156      /// item is erased from the container. It have to be overrided in
157      /// the subclasses.
158       
159      virtual void erase(const Item&) = 0;
160
[1718]161      /// \brief The member function to notificate the observer about
162      /// more item is erased from the container.
163      ///
164      /// The erase() member function notificates the observer about more item
165      /// is erased from the container. It have to be overrided in the
166      /// subclasses.
[1414]167      virtual void erase(const std::vector<Item>& items) {
168        for (int i = 0; i < (int)items.size(); ++i) {
[1701]169          erase(items[i]);
[1414]170        }
171      }
172
[946]173      /// \brief The member function to notificate the observer about the
[1204]174      /// container is built.
[946]175      ///
176      /// The build() member function notificates the observer about the
[1204]177      /// container is built from an empty container. It have to be
[946]178      /// overrided in the subclasses.
179
180      virtual void build() = 0;
181
182      /// \brief The member function to notificate the observer about all
183      /// items are erased from the container.
184      ///
185      /// The clear() member function notificates the observer about all
186      /// items are erased from the container. It have to be overrided in
187      /// the subclasses.
188     
189      virtual void clear() = 0;
190
191    };
192       
193  protected:
194       
195
196    typedef std::vector<ObserverBase*> Container;
197
198    Container container;
199
200               
201  public:
202
203    /// Default constructor.
204       
205    ///
[1038]206    /// The default constructor of the AlterationNotifier.
[946]207    /// It creates an empty registry.
[1038]208    AlterationNotifier() {}
[946]209
[1038]210    /// Copy Constructor of the AlterationNotifier.
[946]211       
[1038]212    /// Copy constructor of the AlterationNotifier.
[946]213    /// It creates only an empty registry because the copiable
214    /// registry's observers have to be registered still into that registry.
[1039]215    AlterationNotifier(const AlterationNotifier&) {}
[946]216
217    /// Assign operator.
218               
[1038]219    /// Assign operator for the AlterationNotifier.
[1040]220    /// It makes the notifier only empty because the copiable
221    /// notifier's observers have to be registered still into that registry.
[1039]222    AlterationNotifier& operator=(const AlterationNotifier&) {
[946]223      typename Container::iterator it;
224      for (it = container.begin(); it != container.end(); ++it) {
225        (*it)->registry = 0;
226      }
227    }
228
229    /// Destructor.
230                               
[1038]231    /// Destructor of the AlterationNotifier.
[946]232    ///
[1038]233    ~AlterationNotifier() {
[946]234      typename Container::iterator it;
235      for (it = container.begin(); it != container.end(); ++it) {
236        (*it)->registry = 0;
237      }
238    }
239       
240       
241  protected:
242
243    void attach(ObserverBase& observer) {
244      container.push_back(&observer);
245      observer.registry = this;
246      observer.registry_index = container.size()-1;
247    }
248
249    void detach(ObserverBase& base) {
250      container.back()->registry_index = base.registry_index;
251      container[base.registry_index] = container.back();
252      container.pop_back();
253      base.registry = 0;
254    }
255
256  public:
257       
[1414]258    /// \brief Notifies all the registered observers about an Item added to
259    /// the container.
260    ///
261    /// It notifies all the registered observers about an Item added to
262    /// the container.
[946]263    ///
[1414]264    void add(const Item& item) {
[946]265      typename Container::iterator it;
266      for (it = container.begin(); it != container.end(); ++it) {
[1414]267        (*it)->add(item);
[946]268      }
269    }   
270
[1414]271    /// \brief Notifies all the registered observers about more Item added to
272    /// the container.
273    ///
274    /// It notifies all the registered observers about more Item added to
275    /// the container.
276    ///
277    void add(const std::vector<Item>& items) {
278      typename Container::iterator it;
279      for (it = container.begin(); it != container.end(); ++it) {
280        (*it)->add(items);
281      }
282    }   
283
284    /// \brief Notifies all the registered observers about an Item erased from
285    /// the container.
286    ///
287    /// It notifies all the registered observers about an Item erased from
288    /// the container.
[946]289    ///
290    void erase(const Item& key) {
291      typename Container::iterator it;
292      for (it = container.begin(); it != container.end(); ++it) {
293        (*it)->erase(key);
294      }
295    }
[1414]296
297    /// \brief Notifies all the registered observers about more Item erased 
298    /// from the container.
299    ///
300    /// It notifies all the registered observers about more Item erased from
301    /// the container.
302    ///
303    void erase(const std::vector<Item>& items) {
304      typename Container::iterator it;
305      for (it = container.begin(); it != container.end(); ++it) {
306        (*it)->erase(items);
307      }
308    }
[946]309
[1414]310    /// \brief Notifies all the registered observers about the container is
311    /// built.
312    ///         
[1204]313    /// Notifies all the registered observers about the container is built
[946]314    /// from an empty container.
315    void build() {
316      typename Container::iterator it;
317      for (it = container.begin(); it != container.end(); ++it) {
318        (*it)->build();
319      }
320    }
321
322
[1414]323    /// \brief Notifies all the registered observers about all Items are
324    /// erased.
325    ///
[946]326    /// Notifies all the registered observers about all Items are erased
327    /// from the container.
328    void clear() {
329      typename Container::iterator it;
330      for (it = container.begin(); it != container.end(); ++it) {
331        (*it)->clear();
332      }
333    }
334  };
335
336
[962]337  /// \brief Class to extend a graph with the functionality of alteration
338  /// observing.
339  ///
340  /// AlterableGraphExtender extends the _Base graphs functionality with
341  /// the possibility of alteration observing. It defines two observer
342  /// registrys for the nodes and mapes.
343  ///
344  /// \todo Document what "alteration observing" is. And probably find a
345  /// better (shorter) name.
[946]346  ///
347  /// \param _Base is the base class to extend.
348  ///
349  /// \pre _Base is conform to the BaseGraphComponent concept.
350  ///
[962]351  /// \post AlterableGraphExtender<_Base> is conform to the
352  /// AlterableGraphComponent concept.
[946]353  ///
354  /// \author Balazs Dezso
355
356  template <typename _Base>
357  class AlterableGraphExtender : public _Base {
358  public:
359
360    typedef AlterableGraphExtender Graph;
361    typedef _Base Parent;
362
363    typedef typename Parent::Node Node;
364    typedef typename Parent::Edge Edge;
365
[962]366    /// The edge observer registry.
[1039]367    typedef AlterationNotifier<Edge> EdgeNotifier;
[946]368    /// The node observer registry.
[1039]369    typedef AlterationNotifier<Node> NodeNotifier;
[946]370
371
372  protected:
373
[1040]374    mutable EdgeNotifier edge_notifier;
[946]375
[1040]376    mutable NodeNotifier node_notifier;
[946]377
378  public:
379
[1134]380    /// \brief Gives back the edge alteration notifier.
381    ///
382    /// Gives back the edge alteration notifier.
383    EdgeNotifier& getNotifier(Edge) const {
[1040]384      return edge_notifier;
[946]385    }
386
[1134]387    /// \brief Gives back the node alteration notifier.
388    ///
389    /// Gives back the node alteration notifier.
390    NodeNotifier& getNotifier(Node) const {
[1040]391      return node_notifier;
[946]392    }
393
394    ~AlterableGraphExtender() {
[1040]395      node_notifier.clear();
396      edge_notifier.clear();
[946]397    }
398   
399  };
400
[1842]401
402  template <typename _Base>
403  class AlterableEdgeSetExtender : public _Base {
404  public:
405
406    typedef AlterableEdgeSetExtender Graph;
407    typedef _Base Parent;
408
409    typedef typename Parent::Edge Edge;
410
411    /// The edge observer registry.
412    typedef AlterationNotifier<Edge> EdgeNotifier;
413
414  protected:
415
416    mutable EdgeNotifier edge_notifier;
417
418  public:
419
420    /// \brief Gives back the edge alteration notifier.
421    ///
422    /// Gives back the edge alteration notifier.
423    EdgeNotifier& getNotifier(Edge) const {
424      return edge_notifier;
425    }
426
427    ~AlterableEdgeSetExtender() {
428      edge_notifier.clear();
429    }
430   
431  };
432
[962]433  /// \brief Class to extend an undirected graph with the functionality of
434  /// alteration observing.
435  ///
436  /// \todo Document.
437  ///
438  /// \sa AlterableGraphExtender
439  ///
440  /// \bug This should be done some other way. Possibilities: template
441  /// specialization (not very easy, if at all possible); some kind of
442  /// enable_if boost technique?
443
444  template <typename _Base>
[1909]445  class AlterableUGraphExtender
[962]446    : public AlterableGraphExtender<_Base> {
447  public:
448
[1909]449    typedef AlterableUGraphExtender Graph;
[962]450    typedef AlterableGraphExtender<_Base> Parent;
451
[1909]452    typedef typename Parent::UEdge UEdge;
[962]453
454    /// The edge observer registry.
[1909]455    typedef AlterationNotifier<UEdge> UEdgeNotifier;
[962]456
457  protected:
458
[1909]459    mutable UEdgeNotifier u_edge_notifier;
[962]460
[1022]461  public:
462
[1038]463    using Parent::getNotifier;
[1909]464    UEdgeNotifier& getNotifier(UEdge) const {
465      return u_edge_notifier;
[962]466    }
467
[1909]468    ~AlterableUGraphExtender() {
469      u_edge_notifier.clear();
[962]470    }
471  };
[1820]472
[1842]473  template <typename _Base>
[1909]474  class AlterableUEdgeSetExtender
[1842]475    : public AlterableEdgeSetExtender<_Base> {
476  public:
477
[1909]478    typedef AlterableUEdgeSetExtender Graph;
[1842]479    typedef AlterableEdgeSetExtender<_Base> Parent;
480
[1909]481    typedef typename Parent::UEdge UEdge;
[1842]482
[1909]483    typedef AlterationNotifier<UEdge> UEdgeNotifier;
[1842]484
485  protected:
486
[1909]487    mutable UEdgeNotifier u_edge_notifier;
[1842]488
489  public:
490
491    using Parent::getNotifier;
[1909]492    UEdgeNotifier& getNotifier(UEdge) const {
493      return u_edge_notifier;
[1842]494    }
495
[1909]496    ~AlterableUEdgeSetExtender() {
497      u_edge_notifier.clear();
[1842]498    }
499  };
500
501
[1820]502
503  template <typename _Base>
[1910]504  class AlterableBpUGraphExtender : public _Base {
[1820]505  public:
506
507    typedef _Base Parent;
[1910]508    typedef AlterableBpUGraphExtender Graph;
[1820]509 
510    typedef typename Parent::Node Node;
[1910]511    typedef typename Parent::BNode BNode;
512    typedef typename Parent::ANode ANode;
[1820]513    typedef typename Parent::Edge Edge;
[1909]514    typedef typename Parent::UEdge UEdge;
[1820]515 
516 
517    typedef AlterationNotifier<Node> NodeNotifier;
[1910]518    typedef AlterationNotifier<BNode> BNodeNotifier;
519    typedef AlterationNotifier<ANode> ANodeNotifier;
[1820]520    typedef AlterationNotifier<Edge> EdgeNotifier;
[1909]521    typedef AlterationNotifier<UEdge> UEdgeNotifier;
[1820]522
523  protected:
524
525    mutable NodeNotifier nodeNotifier;
[1910]526    mutable BNodeNotifier bNodeNotifier;
527    mutable ANodeNotifier aNodeNotifier;
[1820]528    mutable EdgeNotifier edgeNotifier;
[1909]529    mutable UEdgeNotifier uEdgeNotifier;
[1820]530
531  public:
532
533    NodeNotifier& getNotifier(Node) const {
534      return nodeNotifier;
535    }
536
[1910]537    BNodeNotifier& getNotifier(BNode) const {
538      return bNodeNotifier;
[1820]539    }
540
[1910]541    ANodeNotifier& getNotifier(ANode) const {
542      return aNodeNotifier;
[1820]543    }
544
545    EdgeNotifier& getNotifier(Edge) const {
546      return edgeNotifier;
547    }
548
[1909]549    UEdgeNotifier& getNotifier(UEdge) const {
550      return uEdgeNotifier;
[1820]551    }
552
[1910]553    ~AlterableBpUGraphExtender() {
[1820]554      nodeNotifier.clear();
[1910]555      bNodeNotifier.clear();
556      aNodeNotifier.clear();
[1820]557      edgeNotifier.clear();
[1909]558      uEdgeNotifier.clear();
[1820]559    }
560
561  };
[946]562 
563/// @}
564 
565
566}
567
568#endif
Note: See TracBrowser for help on using the repository browser.