ipc/chromium/src/base/observer_list.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
     2 // Use of this source code is governed by a BSD-style license that can be
     3 // found in the LICENSE file.
     5 #ifndef BASE_OBSERVER_LIST_H__
     6 #define BASE_OBSERVER_LIST_H__
     8 #include <algorithm>
     9 #include <limits>
    10 #include <vector>
    12 #include "base/basictypes.h"
    13 #include "base/logging.h"
    15 #if defined(ANDROID) && defined(_STLP_STD_NAME)
    16 using _STLP_STD_NAME::find;
    17 #endif
    19 namespace base {
    21 ///////////////////////////////////////////////////////////////////////////////
    22 //
    23 // OVERVIEW:
    24 //
    25 //   A container for a list of observers.  Unlike a normal STL vector or list,
    26 //   this container can be modified during iteration without invalidating the
    27 //   iterator.  So, it safely handles the case of an observer removing itself
    28 //   or other observers from the list while observers are being notified.
    29 //
    30 // TYPICAL USAGE:
    31 //
    32 //   class MyWidget {
    33 //    public:
    34 //     ...
    35 //
    36 //     class Observer {
    37 //      public:
    38 //       virtual void OnFoo(MyWidget* w) = 0;
    39 //       virtual void OnBar(MyWidget* w, int x, int y) = 0;
    40 //     };
    41 //
    42 //     void AddObserver(Observer* obs) {
    43 //       observer_list_.AddObserver(obs);
    44 //     }
    45 //
    46 //     void RemoveObserver(Observer* obs) {
    47 //       observer_list_.RemoveObserver(obs);
    48 //     }
    49 //
    50 //     void NotifyFoo() {
    51 //       FOR_EACH_OBSERVER(Observer, observer_list_, OnFoo(this));
    52 //     }
    53 //
    54 //     void NotifyBar(int x, int y) {
    55 //       FOR_EACH_OBSERVER(Observer, observer_list_, OnBar(this, x, y));
    56 //     }
    57 //
    58 //    private:
    59 //     ObserverList<Observer> observer_list_;
    60 //   };
    61 //
    62 //
    63 ///////////////////////////////////////////////////////////////////////////////
    65 template <class ObserverType, bool check_empty = false>
    66 class ObserverList {
    67  public:
    68   // Enumeration of which observers are notified.
    69   enum NotificationType {
    70     // Specifies that any observers added during notification are notified.
    71     // This is the default type if non type is provided to the constructor.
    72     NOTIFY_ALL,
    74     // Specifies that observers added while sending out notification are not
    75     // notified.
    76     NOTIFY_EXISTING_ONLY
    77   };
    79   ObserverList() : notify_depth_(0), type_(NOTIFY_ALL) {}
    80   ObserverList(NotificationType type) : notify_depth_(0), type_(type) {}
    81   ~ObserverList() {
    82     // When check_empty is true, assert that the list is empty on destruction.
    83     if (check_empty) {
    84       Compact();
    85       DCHECK_EQ(observers_.size(), 0U);
    86     }
    87   }
    89   // Add an observer to the list.
    90   void AddObserver(ObserverType* obs) {
    91     DCHECK(find(observers_.begin(), observers_.end(), obs) == observers_.end())
    92         << "Observers can only be added once!";
    93     observers_.push_back(obs);
    94   }
    96   // Remove an observer from the list.
    97   void RemoveObserver(ObserverType* obs) {
    98     typename ListType::iterator it =
    99       std::find(observers_.begin(), observers_.end(), obs);
   100     if (it != observers_.end()) {
   101       if (notify_depth_) {
   102         *it = 0;
   103       } else {
   104         observers_.erase(it);
   105       }
   106     }
   107   }
   109   size_t size() const {
   110     return observers_.size();
   111   }
   113   ObserverType* GetElementAt(int index) const {
   114     return observers_[index];
   115   }
   117   // An iterator class that can be used to access the list of observers.  See
   118   // also the FOREACH_OBSERVER macro defined below.
   119   class Iterator {
   120    public:
   121     Iterator(const ObserverList<ObserverType>& list)
   122         : list_(list),
   123           index_(0),
   124           max_index_(list.type_ == NOTIFY_ALL ?
   125                      std::numeric_limits<size_t>::max() :
   126                      list.observers_.size()) {
   127       ++list_.notify_depth_;
   128     }
   130     ~Iterator() {
   131       if (--list_.notify_depth_ == 0)
   132         list_.Compact();
   133     }
   135     ObserverType* GetNext() {
   136       ListType& observers = list_.observers_;
   137       // Advance if the current element is null
   138       size_t max_index = std::min(max_index_, observers.size());
   139       while (index_ < max_index && !observers[index_])
   140         ++index_;
   141       return index_ < max_index ? observers[index_++] : NULL;
   142     }
   144    private:
   145     const ObserverList<ObserverType>& list_;
   146     size_t index_;
   147     size_t max_index_;
   148   };
   150  private:
   151   typedef std::vector<ObserverType*> ListType;
   153   void Compact() const {
   154     typename ListType::iterator it = observers_.begin();
   155     while (it != observers_.end()) {
   156       if (*it) {
   157         ++it;
   158       } else {
   159         it = observers_.erase(it);
   160       }
   161     }
   162   }
   164   // These are marked mutable to facilitate having NotifyAll be const.
   165   mutable ListType observers_;
   166   mutable int notify_depth_;
   167   NotificationType type_;
   169   friend class ObserverList::Iterator;
   171   DISALLOW_EVIL_CONSTRUCTORS(ObserverList);
   172 };
   174 } // namespace base
   176 #define FOR_EACH_OBSERVER(ObserverType, observer_list, func)		\
   177   do {									\
   178     base::ObserverList<ObserverType>::Iterator it(observer_list);	\
   179     ObserverType* obs;							\
   180     while ((obs = it.GetNext()) != NULL)				\
   181       obs->func;							\
   182   } while (0)
   184 #endif  // BASE_OBSERVER_LIST_H__

mercurial