tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

observer_list.h (5184B)


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