lemon/bits/alteration_notifier.h
author deba
Fri, 14 Oct 2005 10:52:15 +0000
changeset 1721 c0f5e8401373
parent 1701 77bb84387815
child 1729 06f939455cb1
permissions -rw-r--r--
Named parameter for heap and cross ref
It needs some redesign
klao@946
     1
/* -*- C++ -*-
ladanyi@1435
     2
 * lemon/notifier.h - Part of LEMON, a generic C++ optimization library
klao@946
     3
 *
alpar@1164
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1359
     5
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
klao@946
     6
 *
klao@946
     7
 * Permission to use, modify and distribute this software is granted
klao@946
     8
 * provided that this copyright notice appears in all copies. For
klao@946
     9
 * precise terms see the accompanying LICENSE file.
klao@946
    10
 *
klao@946
    11
 * This software is provided "AS IS" with no warranty of any kind,
klao@946
    12
 * express or implied, and with no claim as to its suitability for any
klao@946
    13
 * purpose.
klao@946
    14
 *
klao@946
    15
 */
klao@946
    16
klao@946
    17
#ifndef LEMON_ALTERATION_OBSERVER_REGISTRY_H
klao@946
    18
#define LEMON_ALTERATION_OBSERVER_REGISTRY_H
klao@946
    19
klao@946
    20
#include <vector>
klao@946
    21
#include <algorithm>
klao@946
    22
alpar@1587
    23
///\ingroup graphmapfactory
klao@946
    24
///\file
klao@946
    25
///\brief Observer registry for graph alteration observers.
klao@946
    26
klao@946
    27
namespace lemon {
klao@946
    28
alpar@1587
    29
  /// \addtogroup graphmapfactory
klao@946
    30
  /// @{
klao@946
    31
deba@1414
    32
  /// \brief Registry class to register objects observes alterations in 
deba@1414
    33
  /// the graph.
deba@1414
    34
  ///
klao@946
    35
  /// This class is a registry for the objects which observe the
klao@946
    36
  /// alterations in a container. The alteration observers can be attached
klao@946
    37
  /// to and detached from the registry. The observers have to inherit
deba@1038
    38
  /// from the \ref AlterationNotifier::ObserverBase and override
klao@946
    39
  /// the virtual functions in that.
klao@946
    40
  ///
klao@946
    41
  /// The most important application of the alteration observing is the
deba@1414
    42
  /// dynamic map implementation.
klao@946
    43
  ///
klao@946
    44
  /// \param _Item The item type what the observers are observing, usually
klao@946
    45
  /// edge or node.
klao@946
    46
  ///
klao@946
    47
  /// \author Balazs Dezso
klao@946
    48
klao@946
    49
  template <typename _Item>
deba@1038
    50
  class AlterationNotifier {
klao@946
    51
  public:
klao@946
    52
    typedef _Item Item;
klao@946
    53
klao@946
    54
    /// ObserverBase is the base class for the observers.
klao@946
    55
	
klao@946
    56
    /// ObserverBase is the abstract base class for the observers.
klao@946
    57
    /// It will be notified about an item was inserted into or
klao@946
    58
    /// erased from the graph.
klao@946
    59
    ///
klao@946
    60
    /// The observer interface contains some pure virtual functions
klao@946
    61
    /// to override. The add() and erase() functions are
klao@946
    62
    /// to notify the oberver when one item is added or
klao@946
    63
    /// erased.
klao@946
    64
    ///
klao@946
    65
    /// The build() and clear() members are to notify the observer
alpar@1204
    66
    /// about the container is built from an empty container or
klao@946
    67
    /// is cleared to an empty container. 
klao@946
    68
    /// 
klao@946
    69
    /// \author Balazs Dezso
klao@946
    70
klao@946
    71
    class ObserverBase {
klao@946
    72
    protected:
deba@1038
    73
      typedef AlterationNotifier Registry;
klao@946
    74
deba@1038
    75
      friend class AlterationNotifier;
klao@946
    76
deba@1414
    77
      /// \brief Default constructor.
deba@1414
    78
      ///
klao@946
    79
      /// Default constructor for ObserverBase.
klao@946
    80
      /// 
klao@946
    81
      ObserverBase() : registry(0) {}
klao@946
    82
deba@1685
    83
      ObserverBase(const ObserverBase& copy) {
deba@1685
    84
	if (copy.attached()) {
deba@1685
    85
	  copy.getRegistry()->attach(*this);
deba@1685
    86
	}
deba@1685
    87
      }
deba@1685
    88
	
klao@946
    89
      virtual ~ObserverBase() {}
klao@946
    90
deba@1414
    91
      /// \brief Attaches the observer into an AlterationNotifier.
deba@1414
    92
      ///
deba@1038
    93
      /// This member attaches the observer into an AlterationNotifier.
klao@946
    94
      ///
deba@1038
    95
      void attach(AlterationNotifier& r) {
klao@946
    96
	registry = &r;
klao@946
    97
	registry->attach(*this);
klao@946
    98
      }
klao@946
    99
deba@1414
   100
      /// \brief Detaches the observer into an AlterationNotifier.
deba@1414
   101
      ///
deba@1038
   102
      /// This member detaches the observer from an AlterationNotifier.
klao@946
   103
      ///
klao@946
   104
      void detach() {
klao@946
   105
	if (registry) {
klao@946
   106
	  registry->detach(*this);
klao@946
   107
	}
klao@946
   108
      }
klao@946
   109
	
klao@946
   110
klao@946
   111
      /// Gives back a pointer to the registry what the map attached into.
klao@946
   112
klao@946
   113
      /// This function gives back a pointer to the registry what the map
klao@946
   114
      /// attached into.
klao@946
   115
      ///
klao@946
   116
      Registry* getRegistry() const { return const_cast<Registry*>(registry); }
klao@946
   117
      
klao@946
   118
      /// Gives back true when the observer is attached into a registry.
klao@946
   119
      bool attached() const { return registry != 0; }
deba@1685
   120
klao@946
   121
    private:
klao@946
   122
klao@946
   123
      ObserverBase& operator=(const ObserverBase& copy);
klao@946
   124
klao@946
   125
    protected:
klao@946
   126
      
klao@946
   127
      Registry* registry;
klao@946
   128
      int registry_index;
klao@946
   129
klao@946
   130
    public:
klao@946
   131
klao@946
   132
      /// \brief The member function to notificate the observer about an
klao@946
   133
      /// item is added to the container.
klao@946
   134
      ///
klao@946
   135
      /// The add() member function notificates the observer about an item
klao@946
   136
      /// is added to the container. It have to be overrided in the
klao@946
   137
      /// subclasses.
klao@946
   138
	
deba@1414
   139
      virtual void add(const Item&) = 0;
klao@946
   140
deba@1414
   141
      /// \brief The member function to notificate the observer about 
deba@1718
   142
      /// more item is added to the container.
deba@1414
   143
      ///
deba@1718
   144
      /// The add() member function notificates the observer about more item
deba@1414
   145
      /// is added to the container. It have to be overrided in the
deba@1414
   146
      /// subclasses.
deba@1414
   147
deba@1414
   148
      virtual void add(const std::vector<Item>& items) {
deba@1414
   149
	for (int i = 0; i < (int)items.size(); ++i) {
deba@1414
   150
	  add(items[i]);
deba@1414
   151
	}
deba@1414
   152
      }
klao@946
   153
klao@946
   154
      /// \brief The member function to notificate the observer about an
klao@946
   155
      /// item is erased from the container.
klao@946
   156
      ///
klao@946
   157
      /// The erase() member function notificates the observer about an
klao@946
   158
      /// item is erased from the container. It have to be overrided in
klao@946
   159
      /// the subclasses.
klao@946
   160
	
klao@946
   161
      virtual void erase(const Item&) = 0;
klao@946
   162
deba@1718
   163
      /// \brief The member function to notificate the observer about 
deba@1718
   164
      /// more item is erased from the container.
deba@1718
   165
      ///
deba@1718
   166
      /// The erase() member function notificates the observer about more item
deba@1718
   167
      /// is erased from the container. It have to be overrided in the
deba@1718
   168
      /// subclasses.
deba@1414
   169
      virtual void erase(const std::vector<Item>& items) {
deba@1414
   170
	for (int i = 0; i < (int)items.size(); ++i) {
deba@1701
   171
	  erase(items[i]);
deba@1414
   172
	}
deba@1414
   173
      }
deba@1414
   174
deba@1718
   175
      /// \brief Signal a property change on the given item.
deba@1718
   176
      ///
deba@1718
   177
      /// Signal a property change on the given item. It should
deba@1718
   178
      /// be used always with the commitChange() function.
deba@1718
   179
      /// This function is called always the property change.
deba@1718
   180
      /// The commitChange() is called always after the change.
deba@1718
   181
      virtual void signalChange(const Item&) {}
deba@1718
   182
deba@1718
   183
      /// \brief Commit the property change on the given item.
deba@1718
   184
      ///
deba@1718
   185
      /// Commit the property change on the given item. It should
deba@1718
   186
      /// be used always with the signalChange() function.
deba@1718
   187
      /// This function is called always the property change.
deba@1718
   188
      /// The commitChange() is called always after the change.
deba@1718
   189
      virtual void commitChange(const Item&) {}
deba@1718
   190
klao@946
   191
      /// \brief The member function to notificate the observer about the
alpar@1204
   192
      /// container is built.
klao@946
   193
      ///
klao@946
   194
      /// The build() member function notificates the observer about the
alpar@1204
   195
      /// container is built from an empty container. It have to be
klao@946
   196
      /// overrided in the subclasses.
klao@946
   197
klao@946
   198
      virtual void build() = 0;
klao@946
   199
klao@946
   200
      /// \brief The member function to notificate the observer about all
klao@946
   201
      /// items are erased from the container.
klao@946
   202
      ///
klao@946
   203
      /// The clear() member function notificates the observer about all
klao@946
   204
      /// items are erased from the container. It have to be overrided in
klao@946
   205
      /// the subclasses.
klao@946
   206
      
klao@946
   207
      virtual void clear() = 0;
klao@946
   208
klao@946
   209
    };
klao@946
   210
	
klao@946
   211
  protected:
klao@946
   212
	
klao@946
   213
klao@946
   214
    typedef std::vector<ObserverBase*> Container; 
klao@946
   215
klao@946
   216
    Container container;
klao@946
   217
klao@946
   218
		
klao@946
   219
  public:
klao@946
   220
klao@946
   221
    /// Default constructor.
klao@946
   222
	
klao@946
   223
    ///
deba@1038
   224
    /// The default constructor of the AlterationNotifier. 
klao@946
   225
    /// It creates an empty registry.
deba@1038
   226
    AlterationNotifier() {}
klao@946
   227
deba@1038
   228
    /// Copy Constructor of the AlterationNotifier. 
klao@946
   229
	
deba@1038
   230
    /// Copy constructor of the AlterationNotifier. 
klao@946
   231
    /// It creates only an empty registry because the copiable
klao@946
   232
    /// registry's observers have to be registered still into that registry.
deba@1039
   233
    AlterationNotifier(const AlterationNotifier&) {}
klao@946
   234
klao@946
   235
    /// Assign operator.
klao@946
   236
		
deba@1038
   237
    /// Assign operator for the AlterationNotifier. 
deba@1040
   238
    /// It makes the notifier only empty because the copiable
deba@1040
   239
    /// notifier's observers have to be registered still into that registry.
deba@1039
   240
    AlterationNotifier& operator=(const AlterationNotifier&) {
klao@946
   241
      typename Container::iterator it;
klao@946
   242
      for (it = container.begin(); it != container.end(); ++it) {
klao@946
   243
	(*it)->registry = 0;
klao@946
   244
      }
klao@946
   245
    }
klao@946
   246
klao@946
   247
    /// Destructor.
klao@946
   248
				
deba@1038
   249
    /// Destructor of the AlterationNotifier.
klao@946
   250
    ///
deba@1038
   251
    ~AlterationNotifier() {
klao@946
   252
      typename Container::iterator it;
klao@946
   253
      for (it = container.begin(); it != container.end(); ++it) {
klao@946
   254
	(*it)->registry = 0;
klao@946
   255
      }
klao@946
   256
    }
klao@946
   257
	
klao@946
   258
	
klao@946
   259
  protected:
klao@946
   260
klao@946
   261
    void attach(ObserverBase& observer) {
klao@946
   262
      container.push_back(&observer);
klao@946
   263
      observer.registry = this;
klao@946
   264
      observer.registry_index = container.size()-1;
klao@946
   265
    } 
klao@946
   266
klao@946
   267
    void detach(ObserverBase& base) {
klao@946
   268
      container.back()->registry_index = base.registry_index; 
klao@946
   269
      container[base.registry_index] = container.back();
klao@946
   270
      container.pop_back();
klao@946
   271
      base.registry = 0;
klao@946
   272
    }
klao@946
   273
klao@946
   274
  public:
klao@946
   275
	
deba@1414
   276
    /// \brief Notifies all the registered observers about an Item added to 
deba@1414
   277
    /// the container.
deba@1414
   278
    ///
deba@1414
   279
    /// It notifies all the registered observers about an Item added to 
deba@1414
   280
    /// the container.
klao@946
   281
    /// 
deba@1414
   282
    void add(const Item& item) {
klao@946
   283
      typename Container::iterator it;
klao@946
   284
      for (it = container.begin(); it != container.end(); ++it) {
deba@1414
   285
	(*it)->add(item);
klao@946
   286
      }
klao@946
   287
    }	
klao@946
   288
deba@1414
   289
    /// \brief Notifies all the registered observers about more Item added to 
deba@1414
   290
    /// the container.
deba@1414
   291
    ///
deba@1414
   292
    /// It notifies all the registered observers about more Item added to 
deba@1414
   293
    /// the container.
deba@1414
   294
    /// 
deba@1414
   295
    void add(const std::vector<Item>& items) {
deba@1414
   296
      typename Container::iterator it;
deba@1414
   297
      for (it = container.begin(); it != container.end(); ++it) {
deba@1414
   298
	(*it)->add(items);
deba@1414
   299
      }
deba@1414
   300
    }	
deba@1414
   301
deba@1414
   302
    /// \brief Notifies all the registered observers about an Item erased from 
deba@1414
   303
    /// the container.
deba@1414
   304
    ///	
deba@1414
   305
    /// It notifies all the registered observers about an Item erased from 
deba@1414
   306
    /// the container.
klao@946
   307
    /// 
klao@946
   308
    void erase(const Item& key) {
klao@946
   309
      typename Container::iterator it;
klao@946
   310
      for (it = container.begin(); it != container.end(); ++it) {
klao@946
   311
	(*it)->erase(key);
klao@946
   312
      }
klao@946
   313
    }
deba@1414
   314
deba@1414
   315
    /// \brief Notifies all the registered observers about more Item erased  
deba@1414
   316
    /// from the container.
deba@1414
   317
    ///	
deba@1414
   318
    /// It notifies all the registered observers about more Item erased from 
deba@1414
   319
    /// the container.
deba@1414
   320
    /// 
deba@1414
   321
    void erase(const std::vector<Item>& items) {
deba@1414
   322
      typename Container::iterator it;
deba@1414
   323
      for (it = container.begin(); it != container.end(); ++it) {
deba@1414
   324
	(*it)->erase(items);
deba@1414
   325
      }
deba@1414
   326
    }
klao@946
   327
    
deba@1718
   328
    /// \brief Signal a property change on the given item.
deba@1718
   329
    ///
deba@1718
   330
    /// Signal a property change on the given item. It should
deba@1718
   331
    /// be used always with the commitChange() function.
deba@1718
   332
    /// This function is called always the property change.
deba@1718
   333
    /// The commitChange() is called always after the change.
deba@1718
   334
    void signalChange(const Item& item) {
deba@1718
   335
      typename Container::iterator it;
deba@1718
   336
      for (it = container.begin(); it != container.end(); ++it) {
deba@1718
   337
	(*it)->signalChange(item);
deba@1718
   338
      }
deba@1718
   339
    }
deba@1718
   340
    
deba@1718
   341
    /// \brief Commit the property change on the given item.
deba@1718
   342
    ///
deba@1718
   343
    /// Commit the property change on the given item. It should
deba@1718
   344
    /// be used always with the signalChange() function.
deba@1718
   345
    /// This function is called always the property change.
deba@1718
   346
    /// The commitChange() is called always after the change.
deba@1718
   347
    void commitChange(const Item& item) {
deba@1718
   348
      typename Container::iterator it;
deba@1718
   349
      for (it = container.begin(); it != container.end(); ++it) {
deba@1718
   350
	(*it)->commitChange(item);
deba@1718
   351
      }
deba@1718
   352
    }
klao@946
   353
deba@1414
   354
    /// \brief Notifies all the registered observers about the container is 
deba@1414
   355
    /// built.
deba@1414
   356
    ///		
alpar@1204
   357
    /// Notifies all the registered observers about the container is built
klao@946
   358
    /// from an empty container.
klao@946
   359
    void build() {
klao@946
   360
      typename Container::iterator it;
klao@946
   361
      for (it = container.begin(); it != container.end(); ++it) {
klao@946
   362
	(*it)->build();
klao@946
   363
      }
klao@946
   364
    }
klao@946
   365
klao@946
   366
deba@1414
   367
    /// \brief Notifies all the registered observers about all Items are 
deba@1414
   368
    /// erased.
deba@1414
   369
    ///
klao@946
   370
    /// Notifies all the registered observers about all Items are erased
klao@946
   371
    /// from the container.
klao@946
   372
    void clear() {
klao@946
   373
      typename Container::iterator it;
klao@946
   374
      for (it = container.begin(); it != container.end(); ++it) {
klao@946
   375
	(*it)->clear();
klao@946
   376
      }
klao@946
   377
    }
klao@946
   378
  };
klao@946
   379
klao@946
   380
klao@962
   381
  /// \brief Class to extend a graph with the functionality of alteration
klao@962
   382
  /// observing.
klao@962
   383
  ///
klao@962
   384
  /// AlterableGraphExtender extends the _Base graphs functionality with
klao@962
   385
  /// the possibility of alteration observing. It defines two observer
klao@962
   386
  /// registrys for the nodes and mapes.
klao@962
   387
  /// 
klao@962
   388
  /// \todo Document what "alteration observing" is. And probably find a
klao@962
   389
  /// better (shorter) name.
klao@946
   390
  ///
klao@946
   391
  /// \param _Base is the base class to extend.
klao@946
   392
  ///
klao@946
   393
  /// \pre _Base is conform to the BaseGraphComponent concept.
klao@946
   394
  ///
klao@962
   395
  /// \post AlterableGraphExtender<_Base> is conform to the
klao@962
   396
  /// AlterableGraphComponent concept.
klao@946
   397
  ///
klao@946
   398
  /// \author Balazs Dezso
klao@946
   399
klao@946
   400
  template <typename _Base> 
klao@946
   401
  class AlterableGraphExtender : public _Base {
klao@946
   402
  public:
klao@946
   403
klao@946
   404
    typedef AlterableGraphExtender Graph;
klao@946
   405
    typedef _Base Parent;
klao@946
   406
klao@946
   407
    typedef typename Parent::Node Node;
klao@946
   408
    typedef typename Parent::Edge Edge;
klao@946
   409
klao@962
   410
    /// The edge observer registry.
deba@1039
   411
    typedef AlterationNotifier<Edge> EdgeNotifier;
klao@946
   412
    /// The node observer registry.
deba@1039
   413
    typedef AlterationNotifier<Node> NodeNotifier;
klao@946
   414
klao@946
   415
klao@946
   416
  protected:
klao@946
   417
deba@1040
   418
    mutable EdgeNotifier edge_notifier;
klao@946
   419
deba@1040
   420
    mutable NodeNotifier node_notifier;
klao@946
   421
klao@946
   422
  public:
klao@946
   423
deba@1134
   424
    /// \brief Gives back the edge alteration notifier.
deba@1134
   425
    ///
deba@1134
   426
    /// Gives back the edge alteration notifier.
deba@1134
   427
    EdgeNotifier& getNotifier(Edge) const {
deba@1040
   428
      return edge_notifier;
klao@946
   429
    }
klao@946
   430
deba@1134
   431
    /// \brief Gives back the node alteration notifier.
deba@1134
   432
    ///
deba@1134
   433
    /// Gives back the node alteration notifier.
deba@1134
   434
    NodeNotifier& getNotifier(Node) const {
deba@1040
   435
      return node_notifier;
klao@946
   436
    }
klao@946
   437
klao@946
   438
    ~AlterableGraphExtender() {
deba@1040
   439
      node_notifier.clear();
deba@1040
   440
      edge_notifier.clear();
klao@946
   441
    }
klao@946
   442
    
klao@946
   443
  };
klao@946
   444
klao@962
   445
  /// \brief Class to extend an undirected graph with the functionality of
klao@962
   446
  /// alteration observing.
klao@962
   447
  ///
klao@962
   448
  /// \todo Document.
klao@962
   449
  ///
klao@962
   450
  /// \sa AlterableGraphExtender
klao@962
   451
  ///
klao@962
   452
  /// \bug This should be done some other way. Possibilities: template
klao@962
   453
  /// specialization (not very easy, if at all possible); some kind of
klao@962
   454
  /// enable_if boost technique?
klao@962
   455
klao@962
   456
  template <typename _Base> 
klao@962
   457
  class AlterableUndirGraphExtender
klao@962
   458
    : public AlterableGraphExtender<_Base> {
klao@962
   459
  public:
klao@962
   460
klao@962
   461
    typedef AlterableUndirGraphExtender Graph;
klao@962
   462
    typedef AlterableGraphExtender<_Base> Parent;
klao@962
   463
klao@962
   464
    typedef typename Parent::UndirEdge UndirEdge;
klao@962
   465
klao@962
   466
    /// The edge observer registry.
deba@1039
   467
    typedef AlterationNotifier<UndirEdge> UndirEdgeNotifier;
klao@962
   468
klao@962
   469
  protected:
klao@962
   470
deba@1040
   471
    mutable UndirEdgeNotifier undir_edge_notifier;
klao@962
   472
klao@1022
   473
  public:
klao@1022
   474
deba@1038
   475
    using Parent::getNotifier;
deba@1039
   476
    UndirEdgeNotifier& getNotifier(UndirEdge) const {
deba@1040
   477
      return undir_edge_notifier;
klao@962
   478
    }
klao@962
   479
klao@962
   480
    ~AlterableUndirGraphExtender() {
deba@1040
   481
      undir_edge_notifier.clear();
klao@962
   482
    }
klao@962
   483
  };
klao@946
   484
  
klao@946
   485
/// @}
klao@946
   486
  
klao@946
   487
klao@946
   488
}
klao@946
   489
klao@946
   490
#endif