lemon/bits/alteration_notifier.h
author deba
Wed, 01 Mar 2006 10:25:30 +0000
changeset 1991 d7442141d9ef
parent 1979 c2992fd74dad
child 1996 5dc13b93f8b4
permissions -rw-r--r--
The graph adadptors can be alteration observed.
In most cases it uses the adapted graph alteration notifiers.
Only special case is now the UndirGraphAdaptor, where
we have to proxy the signals from the graph.

The SubBidirGraphAdaptor is removed, because it doest not
gives more feature than the EdgeSubGraphAdaptor<UndirGraphAdaptor<Graph>>.

The ResGraphAdaptor is based on this composition.
klao@946
     1
/* -*- C++ -*-
klao@946
     2
 *
alpar@1956
     3
 * This file is a part of LEMON, a generic C++ optimization library
alpar@1956
     4
 *
alpar@1956
     5
 * Copyright (C) 2003-2006
alpar@1956
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1956
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
klao@946
     8
 *
klao@946
     9
 * Permission to use, modify and distribute this software is granted
klao@946
    10
 * provided that this copyright notice appears in all copies. For
klao@946
    11
 * precise terms see the accompanying LICENSE file.
klao@946
    12
 *
klao@946
    13
 * This software is provided "AS IS" with no warranty of any kind,
klao@946
    14
 * express or implied, and with no claim as to its suitability for any
klao@946
    15
 * purpose.
klao@946
    16
 *
klao@946
    17
 */
klao@946
    18
deba@1989
    19
#ifndef LEMON_ALTERATION_NOTIFIER_H
deba@1989
    20
#define LEMON_ALTERATION_NOTIFIER_H
klao@946
    21
klao@946
    22
#include <vector>
klao@946
    23
#include <algorithm>
klao@946
    24
alpar@1946
    25
///\ingroup graphmapfactory
klao@946
    26
///\file
klao@946
    27
///\brief Observer registry for graph alteration observers.
klao@946
    28
klao@946
    29
namespace lemon {
klao@946
    30
deba@1989
    31
  /// \addtogroup graphmapfactory
klao@946
    32
  /// @{
klao@946
    33
deba@1414
    34
  /// \brief Registry class to register objects observes alterations in 
deba@1414
    35
  /// the graph.
deba@1414
    36
  ///
klao@946
    37
  /// This class is a registry for the objects which observe the
klao@946
    38
  /// alterations in a container. The alteration observers can be attached
klao@946
    39
  /// to and detached from the registry. The observers have to inherit
deba@1038
    40
  /// from the \ref AlterationNotifier::ObserverBase and override
klao@946
    41
  /// the virtual functions in that.
klao@946
    42
  ///
klao@946
    43
  /// The most important application of the alteration observing is the
deba@1414
    44
  /// dynamic map implementation.
klao@946
    45
  ///
klao@946
    46
  /// \param _Item The item type what the observers are observing, usually
klao@946
    47
  /// edge or node.
klao@946
    48
  ///
klao@946
    49
  /// \author Balazs Dezso
klao@946
    50
klao@946
    51
  template <typename _Item>
deba@1038
    52
  class AlterationNotifier {
klao@946
    53
  public:
deba@1989
    54
deba@1989
    55
    typedef True Notifier;
deba@1989
    56
klao@946
    57
    typedef _Item Item;
klao@946
    58
klao@946
    59
    /// ObserverBase is the base class for the observers.
klao@946
    60
	
klao@946
    61
    /// ObserverBase is the abstract base class for the observers.
klao@946
    62
    /// It will be notified about an item was inserted into or
klao@946
    63
    /// erased from the graph.
klao@946
    64
    ///
klao@946
    65
    /// The observer interface contains some pure virtual functions
klao@946
    66
    /// to override. The add() and erase() functions are
klao@946
    67
    /// to notify the oberver when one item is added or
klao@946
    68
    /// erased.
klao@946
    69
    ///
klao@946
    70
    /// The build() and clear() members are to notify the observer
alpar@1204
    71
    /// about the container is built from an empty container or
klao@946
    72
    /// is cleared to an empty container. 
klao@946
    73
    /// 
klao@946
    74
    /// \author Balazs Dezso
klao@946
    75
klao@946
    76
    class ObserverBase {
klao@946
    77
    protected:
deba@1038
    78
      typedef AlterationNotifier Registry;
klao@946
    79
deba@1038
    80
      friend class AlterationNotifier;
klao@946
    81
deba@1414
    82
      /// \brief Default constructor.
deba@1414
    83
      ///
klao@946
    84
      /// Default constructor for ObserverBase.
klao@946
    85
      /// 
klao@946
    86
      ObserverBase() : registry(0) {}
klao@946
    87
deba@1685
    88
      ObserverBase(const ObserverBase& copy) {
deba@1685
    89
	if (copy.attached()) {
deba@1685
    90
	  copy.getRegistry()->attach(*this);
deba@1685
    91
	}
deba@1685
    92
      }
deba@1685
    93
	
klao@946
    94
      virtual ~ObserverBase() {}
klao@946
    95
deba@1414
    96
      /// \brief Attaches the observer into an AlterationNotifier.
deba@1414
    97
      ///
deba@1038
    98
      /// This member attaches the observer into an AlterationNotifier.
klao@946
    99
      ///
deba@1038
   100
      void attach(AlterationNotifier& r) {
klao@946
   101
	registry = &r;
klao@946
   102
	registry->attach(*this);
klao@946
   103
      }
klao@946
   104
deba@1414
   105
      /// \brief Detaches the observer into an AlterationNotifier.
deba@1414
   106
      ///
deba@1038
   107
      /// This member detaches the observer from an AlterationNotifier.
klao@946
   108
      ///
klao@946
   109
      void detach() {
klao@946
   110
	if (registry) {
klao@946
   111
	  registry->detach(*this);
klao@946
   112
	}
klao@946
   113
      }
klao@946
   114
	
klao@946
   115
klao@946
   116
      /// Gives back a pointer to the registry what the map attached into.
klao@946
   117
klao@946
   118
      /// This function gives back a pointer to the registry what the map
klao@946
   119
      /// attached into.
klao@946
   120
      ///
klao@946
   121
      Registry* getRegistry() const { return const_cast<Registry*>(registry); }
klao@946
   122
      
klao@946
   123
      /// Gives back true when the observer is attached into a registry.
klao@946
   124
      bool attached() const { return registry != 0; }
deba@1685
   125
klao@946
   126
    private:
klao@946
   127
klao@946
   128
      ObserverBase& operator=(const ObserverBase& copy);
klao@946
   129
klao@946
   130
    protected:
klao@946
   131
      
klao@946
   132
      Registry* registry;
klao@946
   133
      int registry_index;
klao@946
   134
klao@946
   135
      /// \brief The member function to notificate the observer about an
klao@946
   136
      /// item is added to the container.
klao@946
   137
      ///
klao@946
   138
      /// The add() member function notificates the observer about an item
klao@946
   139
      /// is added to the container. It have to be overrided in the
klao@946
   140
      /// subclasses.
klao@946
   141
	
deba@1414
   142
      virtual void add(const Item&) = 0;
klao@946
   143
deba@1414
   144
      /// \brief The member function to notificate the observer about 
deba@1718
   145
      /// more item is added to the container.
deba@1414
   146
      ///
deba@1718
   147
      /// The add() member function notificates the observer about more item
deba@1414
   148
      /// is added to the container. It have to be overrided in the
deba@1414
   149
      /// subclasses.
deba@1414
   150
deba@1414
   151
      virtual void add(const std::vector<Item>& items) {
deba@1414
   152
	for (int i = 0; i < (int)items.size(); ++i) {
deba@1414
   153
	  add(items[i]);
deba@1414
   154
	}
deba@1414
   155
      }
klao@946
   156
klao@946
   157
      /// \brief The member function to notificate the observer about an
klao@946
   158
      /// item is erased from the container.
klao@946
   159
      ///
klao@946
   160
      /// The erase() member function notificates the observer about an
klao@946
   161
      /// item is erased from the container. It have to be overrided in
klao@946
   162
      /// the subclasses.
klao@946
   163
	
klao@946
   164
      virtual void erase(const Item&) = 0;
klao@946
   165
deba@1718
   166
      /// \brief The member function to notificate the observer about 
deba@1718
   167
      /// more item is erased from the container.
deba@1718
   168
      ///
deba@1718
   169
      /// The erase() member function notificates the observer about more item
deba@1718
   170
      /// is erased from the container. It have to be overrided in the
deba@1718
   171
      /// subclasses.
deba@1414
   172
      virtual void erase(const std::vector<Item>& items) {
deba@1414
   173
	for (int i = 0; i < (int)items.size(); ++i) {
deba@1701
   174
	  erase(items[i]);
deba@1414
   175
	}
deba@1414
   176
      }
deba@1414
   177
klao@946
   178
      /// \brief The member function to notificate the observer about the
alpar@1204
   179
      /// container is built.
klao@946
   180
      ///
klao@946
   181
      /// The build() member function notificates the observer about the
alpar@1204
   182
      /// container is built from an empty container. It have to be
klao@946
   183
      /// overrided in the subclasses.
klao@946
   184
klao@946
   185
      virtual void build() = 0;
klao@946
   186
klao@946
   187
      /// \brief The member function to notificate the observer about all
klao@946
   188
      /// items are erased from the container.
klao@946
   189
      ///
klao@946
   190
      /// The clear() member function notificates the observer about all
klao@946
   191
      /// items are erased from the container. It have to be overrided in
klao@946
   192
      /// the subclasses.
klao@946
   193
      
klao@946
   194
      virtual void clear() = 0;
klao@946
   195
klao@946
   196
    };
klao@946
   197
	
klao@946
   198
  protected:
klao@946
   199
	
klao@946
   200
klao@946
   201
    typedef std::vector<ObserverBase*> Container; 
klao@946
   202
klao@946
   203
    Container container;
klao@946
   204
klao@946
   205
		
klao@946
   206
  public:
klao@946
   207
klao@946
   208
    /// Default constructor.
klao@946
   209
	
klao@946
   210
    ///
deba@1038
   211
    /// The default constructor of the AlterationNotifier. 
klao@946
   212
    /// It creates an empty registry.
deba@1038
   213
    AlterationNotifier() {}
klao@946
   214
deba@1038
   215
    /// Copy Constructor of the AlterationNotifier. 
klao@946
   216
	
deba@1038
   217
    /// Copy constructor of the AlterationNotifier. 
klao@946
   218
    /// It creates only an empty registry because the copiable
klao@946
   219
    /// registry's observers have to be registered still into that registry.
deba@1039
   220
    AlterationNotifier(const AlterationNotifier&) {}
klao@946
   221
klao@946
   222
    /// Assign operator.
klao@946
   223
		
deba@1038
   224
    /// Assign operator for the AlterationNotifier. 
deba@1040
   225
    /// It makes the notifier only empty because the copiable
deba@1040
   226
    /// notifier's observers have to be registered still into that registry.
deba@1039
   227
    AlterationNotifier& operator=(const AlterationNotifier&) {
klao@946
   228
      typename Container::iterator it;
klao@946
   229
      for (it = container.begin(); it != container.end(); ++it) {
klao@946
   230
	(*it)->registry = 0;
klao@946
   231
      }
klao@946
   232
    }
klao@946
   233
klao@946
   234
    /// Destructor.
klao@946
   235
				
deba@1038
   236
    /// Destructor of the AlterationNotifier.
klao@946
   237
    ///
deba@1038
   238
    ~AlterationNotifier() {
klao@946
   239
      typename Container::iterator it;
klao@946
   240
      for (it = container.begin(); it != container.end(); ++it) {
klao@946
   241
	(*it)->registry = 0;
klao@946
   242
      }
klao@946
   243
    }
klao@946
   244
	
klao@946
   245
	
klao@946
   246
  protected:
klao@946
   247
klao@946
   248
    void attach(ObserverBase& observer) {
klao@946
   249
      container.push_back(&observer);
klao@946
   250
      observer.registry = this;
klao@946
   251
      observer.registry_index = container.size()-1;
klao@946
   252
    } 
klao@946
   253
klao@946
   254
    void detach(ObserverBase& base) {
klao@946
   255
      container.back()->registry_index = base.registry_index; 
klao@946
   256
      container[base.registry_index] = container.back();
klao@946
   257
      container.pop_back();
klao@946
   258
      base.registry = 0;
klao@946
   259
    }
klao@946
   260
klao@946
   261
  public:
klao@946
   262
	
deba@1414
   263
    /// \brief Notifies all the registered observers about an Item added to 
deba@1414
   264
    /// the container.
deba@1414
   265
    ///
deba@1414
   266
    /// It notifies all the registered observers about an Item added to 
deba@1414
   267
    /// the container.
klao@946
   268
    /// 
deba@1414
   269
    void add(const Item& item) {
klao@946
   270
      typename Container::iterator it;
deba@1979
   271
      try {
deba@1979
   272
        for (it = container.begin(); it != container.end(); ++it) {
deba@1979
   273
          (*it)->add(item);
deba@1979
   274
        }
deba@1979
   275
      } catch (...) {
deba@1979
   276
        typename Container::iterator jt;
deba@1979
   277
        for (jt = container.begin(); jt != it; ++it) {
deba@1979
   278
          (*it)->erase(item);
deba@1979
   279
        }
deba@1979
   280
        throw;
klao@946
   281
      }
klao@946
   282
    }	
klao@946
   283
deba@1414
   284
    /// \brief Notifies all the registered observers about more Item added to 
deba@1414
   285
    /// the container.
deba@1414
   286
    ///
deba@1414
   287
    /// It notifies all the registered observers about more Item added to 
deba@1414
   288
    /// the container.
deba@1414
   289
    /// 
deba@1414
   290
    void add(const std::vector<Item>& items) {
deba@1414
   291
      typename Container::iterator it;
deba@1979
   292
      try {
deba@1979
   293
        for (it = container.begin(); it != container.end(); ++it) {
deba@1979
   294
          (*it)->add(items);
deba@1979
   295
        }
deba@1979
   296
      } catch (...) {
deba@1979
   297
        typename Container::iterator jt;
deba@1979
   298
        for (jt = container.begin(); jt != it; ++it) {
deba@1979
   299
          (*it)->erase(items);
deba@1979
   300
        }
deba@1979
   301
        throw;
deba@1414
   302
      }
deba@1414
   303
    }	
deba@1414
   304
deba@1414
   305
    /// \brief Notifies all the registered observers about an Item erased from 
deba@1414
   306
    /// the container.
deba@1414
   307
    ///	
deba@1414
   308
    /// It notifies all the registered observers about an Item erased from 
deba@1414
   309
    /// the container.
klao@946
   310
    /// 
klao@946
   311
    void erase(const Item& key) {
klao@946
   312
      typename Container::iterator it;
klao@946
   313
      for (it = container.begin(); it != container.end(); ++it) {
klao@946
   314
	(*it)->erase(key);
klao@946
   315
      }
klao@946
   316
    }
deba@1414
   317
deba@1414
   318
    /// \brief Notifies all the registered observers about more Item erased  
deba@1414
   319
    /// from the container.
deba@1414
   320
    ///	
deba@1414
   321
    /// It notifies all the registered observers about more Item erased from 
deba@1414
   322
    /// the container.
deba@1414
   323
    /// 
deba@1414
   324
    void erase(const std::vector<Item>& items) {
deba@1414
   325
      typename Container::iterator it;
deba@1414
   326
      for (it = container.begin(); it != container.end(); ++it) {
deba@1414
   327
	(*it)->erase(items);
deba@1414
   328
      }
deba@1414
   329
    }
klao@946
   330
deba@1414
   331
    /// \brief Notifies all the registered observers about the container is 
deba@1414
   332
    /// built.
deba@1414
   333
    ///		
alpar@1204
   334
    /// Notifies all the registered observers about the container is built
klao@946
   335
    /// from an empty container.
klao@946
   336
    void build() {
klao@946
   337
      typename Container::iterator it;
deba@1979
   338
      try {
deba@1979
   339
        for (it = container.begin(); it != container.end(); ++it) {
deba@1979
   340
          (*it)->build();
deba@1979
   341
        }
deba@1979
   342
      } catch (...) {
deba@1979
   343
        typename Container::iterator jt;
deba@1979
   344
        for (jt = container.begin(); jt != it; ++it) {
deba@1979
   345
          (*it)->clear();
deba@1979
   346
        }
deba@1979
   347
        throw;
klao@946
   348
      }
klao@946
   349
    }
klao@946
   350
klao@946
   351
deba@1414
   352
    /// \brief Notifies all the registered observers about all Items are 
deba@1414
   353
    /// erased.
deba@1414
   354
    ///
klao@946
   355
    /// Notifies all the registered observers about all Items are erased
klao@946
   356
    /// from the container.
klao@946
   357
    void clear() {
klao@946
   358
      typename Container::iterator it;
klao@946
   359
      for (it = container.begin(); it != container.end(); ++it) {
klao@946
   360
	(*it)->clear();
klao@946
   361
      }
klao@946
   362
    }
klao@946
   363
  };
klao@946
   364
klao@946
   365
  
klao@946
   366
/// @}
klao@946
   367
  
klao@946
   368
klao@946
   369
}
klao@946
   370
klao@946
   371
#endif