lemon/bits/alteration_notifier.h
author deba
Wed, 01 Mar 2006 13:19:28 +0000
changeset 1993 2115143eceea
parent 1979 c2992fd74dad
child 1996 5dc13b93f8b4
permissions -rw-r--r--
utility, invalid and traits moved to bits
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