| Index: base/observer_list.h
|
| diff --git a/base/observer_list.h b/base/observer_list.h
|
| index afe1f46cd6e31bfaa0456cec8614fd73f3cd0e1e..7543a98180995fba09e4905e78ad1fab275d8d10 100644
|
| --- a/base/observer_list.h
|
| +++ b/base/observer_list.h
|
| @@ -11,6 +11,7 @@
|
| #include <limits>
|
| #include <vector>
|
|
|
| +#include "base/gtest_prod_util.h"
|
| #include "base/logging.h"
|
| #include "base/macros.h"
|
| #include "base/memory/weak_ptr.h"
|
| @@ -46,11 +47,14 @@
|
| // }
|
| //
|
| // void NotifyFoo() {
|
| -// FOR_EACH_OBSERVER(Observer, observer_list_, OnFoo(this));
|
| +// for (auto& observer : observer_list_)
|
| +// observer.OnFoo(this);
|
| // }
|
| //
|
| // void NotifyBar(int x, int y) {
|
| -// FOR_EACH_OBSERVER(Observer, observer_list_, OnBar(this, x, y));
|
| +// for (FooList::iterator i = observer_list.begin(),
|
| +// e = observer_list.end(); i != e; ++i)
|
| +// i->OnBar(this, x, y);
|
| // }
|
| //
|
| // private:
|
| @@ -80,20 +84,69 @@ class ObserverListBase
|
| NOTIFY_EXISTING_ONLY
|
| };
|
|
|
| - // An iterator class that can be used to access the list of observers. See
|
| - // also the FOR_EACH_OBSERVER macro defined below.
|
| - class Iterator {
|
| + // An iterator class that can be used to access the list of observers.
|
| + template <class ContainerType>
|
| + class Iter {
|
| public:
|
| - explicit Iterator(ObserverListBase<ObserverType>* list);
|
| - ~Iterator();
|
| + Iter();
|
| + explicit Iter(ContainerType* list);
|
| + ~Iter();
|
| +
|
| + // Deprecated.
|
| ObserverType* GetNext();
|
|
|
| + // A workaround for C2244. MSVC requires fully qualified type name for
|
| + // return type on a function definition to match a function declaration.
|
| + using ThisType =
|
| + typename ObserverListBase<ObserverType>::template Iter<ContainerType>;
|
| +
|
| + bool operator==(const Iter& other) const;
|
| + bool operator!=(const Iter& other) const;
|
| + ThisType& operator++();
|
| + ObserverType* operator->() const;
|
| + ObserverType& operator*() const;
|
| +
|
| private:
|
| + FRIEND_TEST_ALL_PREFIXES(ObserverListTest, BasicStdIterator);
|
| + FRIEND_TEST_ALL_PREFIXES(ObserverListTest, StdIteratorRemoveFront);
|
| +
|
| + ObserverType* GetCurrent() const;
|
| + void EnsureValidIndex();
|
| +
|
| + size_t clamped_max_index() const {
|
| + return std::min(max_index_, list_->observers_.size());
|
| + }
|
| +
|
| + bool is_end() const { return !list_ || index_ == clamped_max_index(); }
|
| +
|
| WeakPtr<ObserverListBase<ObserverType>> list_;
|
| + // When initially constructed and each time the iterator is incremented,
|
| + // |index_| is guaranteed to point to a non-null index if the iterator
|
| + // has not reached the end of the ObserverList.
|
| size_t index_;
|
| size_t max_index_;
|
| };
|
|
|
| + using Iterator = Iter<ObserverListBase<ObserverType>>;
|
| +
|
| + using iterator = Iter<ObserverListBase<ObserverType>>;
|
| + iterator begin() {
|
| + // An optimization: do not involve weak pointers for empty list.
|
| + // Note: can't use ?: operator here due to some MSVC bug (unit tests fail)
|
| + if (observers_.empty())
|
| + return iterator();
|
| + return iterator(this);
|
| + }
|
| + iterator end() { return iterator(); }
|
| +
|
| + using const_iterator = Iter<const ObserverListBase<ObserverType>>;
|
| + const_iterator begin() const {
|
| + if (observers_.empty())
|
| + return const_iterator();
|
| + return const_iterator(this);
|
| + }
|
| + const_iterator end() const { return const_iterator(); }
|
| +
|
| ObserverListBase() : notify_depth_(0), type_(NOTIFY_ALL) {}
|
| explicit ObserverListBase(NotificationType type)
|
| : notify_depth_(0), type_(type) {}
|
| @@ -124,37 +177,108 @@ class ObserverListBase
|
| int notify_depth_;
|
| NotificationType type_;
|
|
|
| - friend class ObserverListBase::Iterator;
|
| + template <class ContainerType>
|
| + friend class Iter;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(ObserverListBase);
|
| };
|
|
|
| template <class ObserverType>
|
| -ObserverListBase<ObserverType>::Iterator::Iterator(
|
| - ObserverListBase<ObserverType>* list)
|
| - : list_(list->AsWeakPtr()),
|
| +template <class ContainerType>
|
| +ObserverListBase<ObserverType>::Iter<ContainerType>::Iter()
|
| + : index_(0), max_index_(0) {}
|
| +
|
| +template <class ObserverType>
|
| +template <class ContainerType>
|
| +ObserverListBase<ObserverType>::Iter<ContainerType>::Iter(ContainerType* list)
|
| + : list_(const_cast<ObserverListBase<ObserverType>*>(list)->AsWeakPtr()),
|
| index_(0),
|
| max_index_(list->type_ == NOTIFY_ALL ? std::numeric_limits<size_t>::max()
|
| : list->observers_.size()) {
|
| + EnsureValidIndex();
|
| + DCHECK(list_);
|
| ++list_->notify_depth_;
|
| }
|
|
|
| template <class ObserverType>
|
| -ObserverListBase<ObserverType>::Iterator::~Iterator() {
|
| - if (list_.get() && --list_->notify_depth_ == 0)
|
| +template <class ContainerType>
|
| +ObserverListBase<ObserverType>::Iter<ContainerType>::~Iter() {
|
| + if (list_ && --list_->notify_depth_ == 0)
|
| list_->Compact();
|
| }
|
|
|
| template <class ObserverType>
|
| -ObserverType* ObserverListBase<ObserverType>::Iterator::GetNext() {
|
| - if (!list_.get())
|
| +template <class ContainerType>
|
| +bool ObserverListBase<ObserverType>::Iter<ContainerType>::operator==(
|
| + const Iter& other) const {
|
| + if (is_end() && other.is_end())
|
| + return true;
|
| + return list_.get() == other.list_.get() && index_ == other.index_;
|
| +}
|
| +
|
| +template <class ObserverType>
|
| +template <class ContainerType>
|
| +bool ObserverListBase<ObserverType>::Iter<ContainerType>::operator!=(
|
| + const Iter& other) const {
|
| + return !operator==(other);
|
| +}
|
| +
|
| +template <class ObserverType>
|
| +template <class ContainerType>
|
| +typename ObserverListBase<ObserverType>::template Iter<ContainerType>&
|
| + ObserverListBase<ObserverType>::Iter<ContainerType>::operator++() {
|
| + if (list_) {
|
| + ++index_;
|
| + EnsureValidIndex();
|
| + }
|
| + return *this;
|
| +}
|
| +
|
| +template <class ObserverType>
|
| +template <class ContainerType>
|
| +ObserverType* ObserverListBase<ObserverType>::Iter<ContainerType>::operator->()
|
| + const {
|
| + ObserverType* current = GetCurrent();
|
| + DCHECK(current);
|
| + return current;
|
| +}
|
| +
|
| +template <class ObserverType>
|
| +template <class ContainerType>
|
| +ObserverType& ObserverListBase<ObserverType>::Iter<ContainerType>::operator*()
|
| + const {
|
| + ObserverType* current = GetCurrent();
|
| + DCHECK(current);
|
| + return *current;
|
| +}
|
| +
|
| +template <class ObserverType>
|
| +template <class ContainerType>
|
| +ObserverType* ObserverListBase<ObserverType>::Iter<ContainerType>::GetCurrent()
|
| + const {
|
| + if (!list_)
|
| return nullptr;
|
| - ListType& observers = list_->observers_;
|
| - // Advance if the current element is null
|
| - size_t max_index = std::min(max_index_, observers.size());
|
| - while (index_ < max_index && !observers[index_])
|
| + return index_ < clamped_max_index() ? list_->observers_[index_] : nullptr;
|
| +}
|
| +
|
| +template <class ObserverType>
|
| +template <class ContainerType>
|
| +void ObserverListBase<ObserverType>::Iter<ContainerType>::EnsureValidIndex() {
|
| + if (!list_)
|
| + return;
|
| +
|
| + size_t max_index = clamped_max_index();
|
| + while (index_ < max_index && !list_->observers_[index_])
|
| ++index_;
|
| - return index_ < max_index ? observers[index_++] : nullptr;
|
| +}
|
| +
|
| +template <class ObserverType>
|
| +template <class ContainerType>
|
| +ObserverType* ObserverListBase<ObserverType>::Iter<ContainerType>::GetNext() {
|
| + EnsureValidIndex();
|
| + ObserverType* current = GetCurrent();
|
| + operator++();
|
| + return current;
|
| }
|
|
|
| template <class ObserverType>
|
| @@ -205,9 +329,8 @@ void ObserverListBase<ObserverType>::Clear() {
|
|
|
| template <class ObserverType>
|
| void ObserverListBase<ObserverType>::Compact() {
|
| - observers_.erase(
|
| - std::remove(observers_.begin(), observers_.end(), nullptr),
|
| - observers_.end());
|
| + observers_.erase(std::remove(observers_.begin(), observers_.end(), nullptr),
|
| + observers_.end());
|
| }
|
|
|
| template <class ObserverType, bool check_empty = false>
|
| @@ -233,15 +356,11 @@ class ObserverList : public ObserverListBase<ObserverType> {
|
| }
|
| };
|
|
|
| -#define FOR_EACH_OBSERVER(ObserverType, observer_list, func) \
|
| - do { \
|
| - if ((observer_list).might_have_observers()) { \
|
| - typename base::ObserverListBase<ObserverType>::Iterator \
|
| - it_inside_observer_macro(&observer_list); \
|
| - ObserverType* obs; \
|
| - while ((obs = it_inside_observer_macro.GetNext()) != nullptr) \
|
| - obs->func; \
|
| - } \
|
| +// Deprecated. Use the range-based for loop instead.
|
| +#define FOR_EACH_OBSERVER(ObserverType, observer_list, func) \
|
| + do { \
|
| + for (ObserverType & o : observer_list) \
|
| + o.func; \
|
| } while (0)
|
|
|
| } // namespace base
|
|
|