lemon/bits/alteration_notifier.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
parent 2006 00d59f733817
child 2305 4a2236cc98a0
permissions -rw-r--r--
Update the Path concept
Concept check for paths

DirPath renamed to Path
The interface updated to the new lemon interface
Make difference between the empty path and the path from one node
Builder interface have not been changed
// I wanted but there was not accordance about it

UPath is removed
It was a buggy implementation, it could not iterate on the
nodes in the right order
Right way to use undirected paths => path of edges in undirected graphs

The tests have been modified to the current implementation
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@1999
    19
#ifndef LEMON_BITS_ALTERATION_NOTIFIER_H
deba@1999
    20
#define LEMON_BITS_ALTERATION_NOTIFIER_H
klao@946
    21
klao@946
    22
#include <vector>
deba@1999
    23
deba@1999
    24
#include <lemon/bits/utility.h>
klao@946
    25
deba@1996
    26
///\ingroup graphbits
klao@946
    27
///\file
deba@1999
    28
///\brief Observer notifier for graph alteration observers.
klao@946
    29
klao@946
    30
namespace lemon {
klao@946
    31
deba@1999
    32
  /// \ingroup graphbits
deba@1414
    33
  ///
deba@1999
    34
  /// \brief Notifier class to notify observes about alterations in 
deba@1999
    35
  /// a container.
klao@946
    36
  ///
deba@1999
    37
  /// The simple graph's can be refered as two containers, one node container
deba@1999
    38
  /// and one edge container. But they are not standard containers they
deba@1999
    39
  /// does not store values directly they are just key continars for more
deba@1999
    40
  /// value containers which are the node and edge maps.
klao@946
    41
  ///
deba@1999
    42
  /// The graph's node and edge sets can be changed as we add or erase
deba@1999
    43
  /// nodes and edges in the graph. Lemon would like to handle easily
deba@1999
    44
  /// that the node and edge maps should contain values for all nodes or
deba@1999
    45
  /// edges. If we want to check on every indicing if the map contains
deba@1999
    46
  /// the current indicing key that cause a drawback in the performance
alpar@2006
    47
  /// in the library. We use another solution we notify all maps about
deba@1999
    48
  /// an alteration in the graph, which cause only drawback on the
deba@1999
    49
  /// alteration of the graph.
deba@1999
    50
  ///
deba@1999
    51
  /// This class provides an interface to the container. The \e first() and \e 
deba@1999
    52
  /// next() member functions make possible to iterate on the keys of the
deba@1999
    53
  /// container. The \e id() function returns an integer id for each key.
deba@1999
    54
  /// The \e maxId() function gives back an upper bound of the ids.
deba@1999
    55
  ///
deba@1999
    56
  /// For the proper functonality of this class, we should notify it
deba@1999
    57
  /// about each alteration in the container. The alterations have four type
deba@1999
    58
  /// as \e add(), \e erase(), \e build() and \e clear(). The \e add() and
deba@1999
    59
  /// \e erase() signals that only one or few items added or erased to or
deba@1999
    60
  /// from the graph. If all items are erased from the graph or from an empty
deba@1999
    61
  /// graph a new graph is builded then it can be signaled with the
deba@1999
    62
  /// clear() and build() members. Important rule that if we erase items 
deba@1999
    63
  /// from graph we should first signal the alteration and after that erase
deba@1999
    64
  /// them from the container, on the other way on item addition we should
deba@1999
    65
  /// first extend the container and just after that signal the alteration.
deba@1999
    66
  ///
deba@1999
    67
  /// The alteration can be observed with a class inherited from the
deba@1999
    68
  /// \e ObserverBase nested class. The signals can be handled with
deba@2188
    69
  /// overriding the virtual functions defined in the base class.  The
deba@2188
    70
  /// observer base can be attached to the notifier with the 
deba@2188
    71
  /// \e attach() member and can be detached with detach() function. The
deba@2188
    72
  /// alteration handlers should not call any function which signals
deba@2188
    73
  /// an other alteration in the same notifier and should not
deba@2188
    74
  /// detach any observer from the notifier.
deba@1999
    75
  ///
deba@2188
    76
  /// Alteration observers try to be exception safe. If an \e add() or
deba@2188
    77
  /// a \e clear() function throws an exception then the remaining
deba@2188
    78
  /// observeres will not be notified and the fulfilled additions will
deba@2188
    79
  /// be rolled back by calling the \e erase() or \e clear()
deba@2188
    80
  /// functions. Thence the \e erase() and \e clear() should not throw
deba@2188
    81
  /// exception. Actullay, it can be throw only 
deba@2188
    82
  /// \ref AlterationObserver::ImmediateDetach ImmediateDetach
deba@2188
    83
  /// exception which detach the observer from the notifier.
deba@1999
    84
  ///
deba@1999
    85
  /// There are some place when the alteration observing is not completly
deba@1999
    86
  /// reliable. If we want to carry out the node degree in the graph
deba@1999
    87
  /// as in the \ref InDegMap and we use the reverseEdge that cause 
deba@1999
    88
  /// unreliable functionality. Because the alteration observing signals
deba@1999
    89
  /// only erasing and adding but not the reversing it will stores bad
deba@1999
    90
  /// degrees. The sub graph adaptors cannot signal the alterations because
deba@1999
    91
  /// just a setting in the filter map can modify the graph and this cannot
deba@1999
    92
  /// be watched in any way.
deba@1999
    93
  ///
deba@1999
    94
  /// \param _Container The container which is observed.
deba@1999
    95
  /// \param _Item The item type which is obserbved.
klao@946
    96
  ///
klao@946
    97
  /// \author Balazs Dezso
klao@946
    98
deba@1999
    99
  template <typename _Container, typename _Item>
deba@1038
   100
  class AlterationNotifier {
klao@946
   101
  public:
deba@1989
   102
deba@1989
   103
    typedef True Notifier;
deba@1989
   104
deba@1999
   105
    typedef _Container Container;
klao@946
   106
    typedef _Item Item;
klao@946
   107
deba@2188
   108
    /// \brief Exception which can be called from \e clear() and 
deba@2188
   109
    /// \e erase().
deba@2188
   110
    ///
deba@2188
   111
    /// From the \e clear() and \e erase() function only this
deba@2188
   112
    /// exception is allowed to throw. The exception immediatly
deba@2188
   113
    /// detaches the current observer from the notifier. Because the
deba@2188
   114
    /// \e clear() and \e erase() should not throw other exceptions
deba@2188
   115
    /// it can be used to invalidate the observer.
deba@2188
   116
    struct ImmediateDetach {};
deba@2188
   117
deba@1999
   118
    /// \brief ObserverBase is the base class for the observers.
deba@1999
   119
    ///
klao@946
   120
    /// ObserverBase is the abstract base class for the observers.
klao@946
   121
    /// It will be notified about an item was inserted into or
klao@946
   122
    /// erased from the graph.
klao@946
   123
    ///
klao@946
   124
    /// The observer interface contains some pure virtual functions
klao@946
   125
    /// to override. The add() and erase() functions are
klao@946
   126
    /// to notify the oberver when one item is added or
klao@946
   127
    /// erased.
klao@946
   128
    ///
klao@946
   129
    /// The build() and clear() members are to notify the observer
alpar@1204
   130
    /// about the container is built from an empty container or
klao@946
   131
    /// is cleared to an empty container. 
klao@946
   132
    /// 
klao@946
   133
    /// \author Balazs Dezso
klao@946
   134
klao@946
   135
    class ObserverBase {
klao@946
   136
    protected:
deba@1999
   137
      typedef AlterationNotifier Notifier;
klao@946
   138
deba@1038
   139
      friend class AlterationNotifier;
klao@946
   140
deba@1414
   141
      /// \brief Default constructor.
deba@1414
   142
      ///
klao@946
   143
      /// Default constructor for ObserverBase.
klao@946
   144
      /// 
deba@1999
   145
      ObserverBase() : notifier(0) {}
klao@946
   146
deba@1999
   147
      /// \brief Constructor which attach the observer into notifier.
deba@1999
   148
      ///
deba@1999
   149
      /// Constructor which attach the observer into notifier.
deba@1999
   150
      ObserverBase(AlterationNotifier& _notifier) {
deba@1999
   151
        attach(_notifier);
deba@1999
   152
      }
deba@1999
   153
deba@1999
   154
      /// \brief Constructor which attach the obserever to the same notifier.
deba@1999
   155
      ///
deba@1999
   156
      /// Constructor which attach the obserever to the same notifier as
deba@1999
   157
      /// the other observer is attached to. 
deba@1685
   158
      ObserverBase(const ObserverBase& copy) {
deba@1685
   159
	if (copy.attached()) {
deba@1999
   160
          attach(*copy.getNotifier());
deba@1685
   161
	}
deba@1685
   162
      }
deba@1685
   163
	
deba@1999
   164
      /// \brief Destructor
deba@1999
   165
      virtual ~ObserverBase() {
deba@1999
   166
        if (attached()) {
deba@1999
   167
          detach();
deba@1999
   168
        }
deba@1999
   169
      }
klao@946
   170
deba@1414
   171
      /// \brief Attaches the observer into an AlterationNotifier.
deba@1414
   172
      ///
deba@1038
   173
      /// This member attaches the observer into an AlterationNotifier.
klao@946
   174
      ///
deba@1999
   175
      void attach(AlterationNotifier& _notifier) {
deba@1999
   176
	notifier = &_notifier;
deba@1999
   177
	notifier->attach(*this);
klao@946
   178
      }
deba@2188
   179
      
deba@1414
   180
      /// \brief Detaches the observer into an AlterationNotifier.
deba@1414
   181
      ///
deba@1038
   182
      /// This member detaches the observer from an AlterationNotifier.
klao@946
   183
      ///
klao@946
   184
      void detach() {
deba@1999
   185
        notifier->detach(*this);
klao@946
   186
      }
deba@2188
   187
      
deba@1999
   188
      /// \brief Gives back a pointer to the notifier which the map 
klao@946
   189
      /// attached into.
klao@946
   190
      ///
deba@1999
   191
      /// This function gives back a pointer to the notifier which the map
deba@1999
   192
      /// attached into.
deba@1999
   193
      ///
deba@1999
   194
      Notifier* getNotifier() const { return const_cast<Notifier*>(notifier); }
klao@946
   195
      
deba@1999
   196
      /// Gives back true when the observer is attached into a notifier.
deba@1999
   197
      bool attached() const { return notifier != 0; }
deba@1685
   198
klao@946
   199
    private:
klao@946
   200
klao@946
   201
      ObserverBase& operator=(const ObserverBase& copy);
klao@946
   202
klao@946
   203
    protected:
klao@946
   204
      
deba@1999
   205
      Notifier* notifier;
deba@1999
   206
      int notifier_index;
klao@946
   207
klao@946
   208
      /// \brief The member function to notificate the observer about an
klao@946
   209
      /// item is added to the container.
klao@946
   210
      ///
klao@946
   211
      /// The add() member function notificates the observer about an item
klao@946
   212
      /// is added to the container. It have to be overrided in the
klao@946
   213
      /// subclasses.
klao@946
   214
	
deba@1414
   215
      virtual void add(const Item&) = 0;
klao@946
   216
deba@1414
   217
      /// \brief The member function to notificate the observer about 
deba@1718
   218
      /// more item is added to the container.
deba@1414
   219
      ///
deba@1718
   220
      /// The add() member function notificates the observer about more item
deba@1414
   221
      /// is added to the container. It have to be overrided in the
deba@1414
   222
      /// subclasses.
deba@1414
   223
deba@1414
   224
      virtual void add(const std::vector<Item>& items) {
deba@1999
   225
        int i;
deba@1999
   226
        try {
deba@1999
   227
          for (i = 0; i < (int)items.size(); ++i) {
deba@1999
   228
            add(items[i]);
deba@1999
   229
          }
deba@1999
   230
        } catch (...) {
deba@1999
   231
          for (int j = 0; j < i; ++j) {
deba@1999
   232
            add(items[j]);
deba@1999
   233
          }          
deba@1999
   234
          throw;
deba@1999
   235
        }
deba@1414
   236
      }
klao@946
   237
klao@946
   238
      /// \brief The member function to notificate the observer about an
klao@946
   239
      /// item is erased from the container.
klao@946
   240
      ///
klao@946
   241
      /// The erase() member function notificates the observer about an
klao@946
   242
      /// item is erased from the container. It have to be overrided in
klao@946
   243
      /// the subclasses.
klao@946
   244
	
klao@946
   245
      virtual void erase(const Item&) = 0;
klao@946
   246
deba@1718
   247
      /// \brief The member function to notificate the observer about 
deba@1718
   248
      /// more item is erased from the container.
deba@1718
   249
      ///
deba@1718
   250
      /// The erase() member function notificates the observer about more item
deba@1718
   251
      /// is erased from the container. It have to be overrided in the
deba@1718
   252
      /// subclasses.
deba@1414
   253
      virtual void erase(const std::vector<Item>& items) {
deba@1999
   254
        for (int i = 0; i < (int)items.size(); ++i) {
deba@1999
   255
          erase(items[i]);
deba@1999
   256
        }
deba@1414
   257
      }
deba@1414
   258
klao@946
   259
      /// \brief The member function to notificate the observer about the
alpar@1204
   260
      /// container is built.
klao@946
   261
      ///
klao@946
   262
      /// The build() member function notificates the observer about the
alpar@1204
   263
      /// container is built from an empty container. It have to be
klao@946
   264
      /// overrided in the subclasses.
klao@946
   265
deba@1999
   266
      virtual void build() {
deba@1999
   267
        Item it;
deba@1999
   268
        try {
deba@1999
   269
          for (notifier->first(it); it != INVALID; notifier->next(it)) {
deba@1999
   270
            add(it);
deba@1999
   271
          }
deba@1999
   272
        } catch (...) {
deba@1999
   273
          Item jt;
deba@1999
   274
          for (notifier->first(jt); jt != it; notifier->next(jt)) {
deba@1999
   275
            erase(jt);
deba@1999
   276
          }
deba@1999
   277
          throw;
deba@1999
   278
        }
deba@1999
   279
      }
klao@946
   280
klao@946
   281
      /// \brief The member function to notificate the observer about all
klao@946
   282
      /// items are erased from the container.
klao@946
   283
      ///
klao@946
   284
      /// The clear() member function notificates the observer about all
klao@946
   285
      /// items are erased from the container. It have to be overrided in
deba@1999
   286
      /// the subclasses.      
deba@1999
   287
      virtual void clear() {
deba@1999
   288
        Item it;
deba@1999
   289
        for (notifier->first(it); it != INVALID; notifier->next(it)) {
deba@1999
   290
          erase(it);
deba@1999
   291
        }
deba@1999
   292
      }
klao@946
   293
klao@946
   294
    };
klao@946
   295
	
klao@946
   296
  protected:
klao@946
   297
deba@1999
   298
    const Container* container;
klao@946
   299
deba@1999
   300
    typedef std::vector<ObserverBase*> Observers; 
deba@1999
   301
    Observers observers;
klao@946
   302
klao@946
   303
		
klao@946
   304
  public:
klao@946
   305
deba@1999
   306
    /// \brief Default constructor.
klao@946
   307
    ///
deba@1038
   308
    /// The default constructor of the AlterationNotifier. 
deba@1999
   309
    /// It creates an empty notifier.
deba@1999
   310
    AlterationNotifier() 
deba@1999
   311
      : container(0) {}
klao@946
   312
deba@1999
   313
    /// \brief Constructor.
deba@1999
   314
    ///
deba@1999
   315
    /// Constructor with the observed container parameter.
deba@1999
   316
    AlterationNotifier(const Container& _container) 
deba@1999
   317
      : container(&_container) {}
deba@1999
   318
deba@1999
   319
    /// \brief Copy Constructor of the AlterationNotifier. 
deba@1999
   320
    ///
deba@1038
   321
    /// Copy constructor of the AlterationNotifier. 
deba@1999
   322
    /// It creates only an empty notifier because the copiable
deba@1999
   323
    /// notifier's observers have to be registered still into that notifier.
deba@1999
   324
    AlterationNotifier(const AlterationNotifier& _notifier) 
deba@1999
   325
      : container(_notifier.container) {}
klao@946
   326
deba@1999
   327
    /// \brief Destructor.
deba@1999
   328
    ///		
deba@1999
   329
    /// Destructor of the AlterationNotifier.
deba@1999
   330
    ///
deba@1999
   331
    ~AlterationNotifier() {
deba@1999
   332
      typename Observers::iterator it;
deba@1999
   333
      for (it = observers.begin(); it != observers.end(); ++it) {
deba@1999
   334
	(*it)->notifier = 0;
klao@946
   335
      }
klao@946
   336
    }
klao@946
   337
deba@1999
   338
    /// \brief Sets the container.
klao@946
   339
    ///
deba@1999
   340
    /// Sets the container.
deba@1999
   341
    void setContainer(const Container& _container) {
deba@1999
   342
      container = &_container;
klao@946
   343
    }
deba@1999
   344
deba@1999
   345
  protected:
deba@1999
   346
deba@1999
   347
    AlterationNotifier& operator=(const AlterationNotifier&);
deba@1999
   348
deba@1999
   349
  public:
deba@1999
   350
deba@1999
   351
deba@1999
   352
deba@1999
   353
    /// \brief First item in the container.
deba@1999
   354
    ///
deba@1999
   355
    /// Returns the first item in the container. It is
deba@1999
   356
    /// for start the iteration on the container.
deba@1999
   357
    void first(Item& item) const {
deba@1999
   358
      container->first(item);
deba@1999
   359
    }
deba@1999
   360
deba@1999
   361
    /// \brief Next item in the container.
deba@1999
   362
    ///
deba@1999
   363
    /// Returns the next item in the container. It is
deba@1999
   364
    /// for iterate on the container.
deba@1999
   365
    void next(Item& item) const {
deba@1999
   366
      container->next(item);
deba@1999
   367
    }
deba@1999
   368
deba@1999
   369
    /// \brief Returns the id of the item.
deba@1999
   370
    ///
deba@1999
   371
    /// Returns the id of the item provided by the container.
deba@1999
   372
    int id(const Item& item) const {
deba@1999
   373
      return container->id(item);
deba@1999
   374
    }
deba@1999
   375
deba@1999
   376
    /// \brief Returns the maximum id of the container.
deba@1999
   377
    ///
deba@1999
   378
    /// Returns the maximum id of the container.
deba@1999
   379
    int maxId() const {
deba@1999
   380
      return container->maxId(Item());
deba@1999
   381
    }
deba@1999
   382
		
klao@946
   383
  protected:
klao@946
   384
klao@946
   385
    void attach(ObserverBase& observer) {
deba@1999
   386
      observers.push_back(&observer);
deba@1999
   387
      observer.notifier = this;
deba@1999
   388
      observer.notifier_index = observers.size() - 1;
klao@946
   389
    } 
klao@946
   390
deba@1999
   391
    void detach(ObserverBase& observer) {
deba@1999
   392
      observers.back()->notifier_index = observer.notifier_index; 
deba@1999
   393
      observers[observer.notifier_index] = observers.back();
deba@1999
   394
      observers.pop_back();
deba@1999
   395
      observer.notifier = 0;
klao@946
   396
    }
klao@946
   397
klao@946
   398
  public:
klao@946
   399
	
deba@1999
   400
    /// \brief Notifies all the registed observers about an item added to 
deba@1414
   401
    /// the container.
deba@1414
   402
    ///
deba@1999
   403
    /// It notifies all the registed observers about an item added to 
deba@1414
   404
    /// the container.
klao@946
   405
    /// 
deba@1414
   406
    void add(const Item& item) {
deba@1999
   407
      typename Observers::iterator it;
deba@1979
   408
      try {
deba@1999
   409
        for (it = observers.begin(); it != observers.end(); ++it) {
deba@1979
   410
          (*it)->add(item);
deba@1979
   411
        }
deba@1979
   412
      } catch (...) {
deba@1999
   413
        typename Observers::iterator jt;
deba@1999
   414
        for (jt = observers.begin(); jt != it; ++jt) {
deba@1979
   415
          (*it)->erase(item);
deba@1979
   416
        }
deba@1979
   417
        throw;
klao@946
   418
      }
klao@946
   419
    }	
klao@946
   420
deba@1999
   421
    /// \brief Notifies all the registed observers about more item added to 
deba@1414
   422
    /// the container.
deba@1414
   423
    ///
deba@1999
   424
    /// It notifies all the registed observers about more item added to 
deba@1414
   425
    /// the container.
deba@1414
   426
    /// 
deba@1414
   427
    void add(const std::vector<Item>& items) {
deba@1999
   428
      typename Observers::iterator it;
deba@1979
   429
      try {
deba@1999
   430
        for (it = observers.begin(); it != observers.end(); ++it) {
deba@1979
   431
          (*it)->add(items);
deba@1979
   432
        }
deba@1979
   433
      } catch (...) {
deba@1999
   434
        typename Observers::iterator jt;
deba@1999
   435
        for (jt = observers.begin(); jt != it; ++jt) {
deba@1979
   436
          (*it)->erase(items);
deba@1979
   437
        }
deba@1979
   438
        throw;
deba@1414
   439
      }
deba@1414
   440
    }	
deba@1414
   441
deba@1999
   442
    /// \brief Notifies all the registed observers about an item erased from 
deba@1414
   443
    /// the container.
deba@1414
   444
    ///	
deba@1999
   445
    /// It notifies all the registed observers about an item erased from 
deba@1414
   446
    /// the container.
klao@946
   447
    /// 
deba@2188
   448
    void erase(const Item& key) throw() {
deba@2188
   449
      int i = 0;
deba@2188
   450
      while (i != (int)observers.size()) {
deba@2188
   451
        try {
deba@2188
   452
          observers[i]->erase(key);
deba@2188
   453
          ++i;
deba@2188
   454
        } catch (const ImmediateDetach&) {
deba@2188
   455
          observers[i]->detach();
deba@2188
   456
        }
klao@946
   457
      }
klao@946
   458
    }
deba@1414
   459
deba@1999
   460
    /// \brief Notifies all the registed observers about more item erased  
deba@1414
   461
    /// from the container.
deba@1414
   462
    ///	
deba@1999
   463
    /// It notifies all the registed observers about more item erased from 
deba@1414
   464
    /// the container.
deba@1414
   465
    /// 
deba@1414
   466
    void erase(const std::vector<Item>& items) {
deba@2188
   467
      int i = 0;
deba@2188
   468
      while (i != (int)observers.size()) {
deba@2188
   469
        try {
deba@2188
   470
          observers[i]->erase(items);
deba@2188
   471
          ++i;
deba@2188
   472
        } catch (const ImmediateDetach&) {
deba@2188
   473
          observers[i]->detach();
deba@2188
   474
        }
deba@1414
   475
      }
deba@1414
   476
    }
klao@946
   477
deba@1999
   478
    /// \brief Notifies all the registed observers about the container is 
deba@1414
   479
    /// built.
deba@1414
   480
    ///		
deba@1999
   481
    /// Notifies all the registed observers about the container is built
klao@946
   482
    /// from an empty container.
klao@946
   483
    void build() {
deba@1999
   484
      typename Observers::iterator it;
deba@1979
   485
      try {
deba@1999
   486
        for (it = observers.begin(); it != observers.end(); ++it) {
deba@1979
   487
          (*it)->build();
deba@1979
   488
        }
deba@1979
   489
      } catch (...) {
deba@1999
   490
        typename Observers::iterator jt;
deba@1999
   491
        for (jt = observers.begin(); jt != it; ++jt) {
deba@1979
   492
          (*it)->clear();
deba@1979
   493
        }
deba@1979
   494
        throw;
klao@946
   495
      }
klao@946
   496
    }
klao@946
   497
deba@1999
   498
    /// \brief Notifies all the registed observers about all items are 
deba@1414
   499
    /// erased.
deba@1414
   500
    ///
deba@1999
   501
    /// Notifies all the registed observers about all items are erased
klao@946
   502
    /// from the container.
klao@946
   503
    void clear() {
deba@2188
   504
      int i = 0;
deba@2188
   505
      while (i != (int)observers.size()) {
deba@2188
   506
        try {
deba@2188
   507
          observers[i]->clear();
deba@2188
   508
          ++i;
deba@2188
   509
        } catch (const ImmediateDetach&) {
deba@2188
   510
          observers[i]->detach();
deba@2188
   511
        }
klao@946
   512
      }
klao@946
   513
    }
klao@946
   514
  };
klao@946
   515
klao@946
   516
}
klao@946
   517
klao@946
   518
#endif