Index: base/observer_list.h |
diff --git a/base/observer_list.h b/base/observer_list.h |
index afe1f46cd6e31bfaa0456cec8614fd73f3cd0e1e..a4e7f80364c00c415bd2d4010a23c14b2d682e7c 100644 |
--- a/base/observer_list.h |
+++ b/base/observer_list.h |
@@ -46,10 +46,21 @@ |
// } |
// |
// 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 (FooList::iterator i = observer_list.begin(), |
+// e = observer_list.end(); i != e; ++i) |
+// i->OnBar(this, x, y); |
+// } |
+// |
+// void NotifyFooDeprecated() { |
+// FOR_EACH_OBSERVER(Observer, observer_list_, OnFoo(this)); |
+// } |
+// |
+// void NotifyBarDeprecated(int x, int y) { |
// FOR_EACH_OBSERVER(Observer, observer_list_, OnBar(this, x, y)); |
// } |
// |
@@ -80,20 +91,51 @@ 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(); |
+ |
ObserverType* GetNext(); |
+ ObserverType* GetCurrent() const; |
+ void Advance(); |
+ |
+ // 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; |
+ ThisType& operator++(); |
+ ThisType operator++(int); |
dcheng
2016/09/16 21:44:17
Do we need to provide both prefix and postfix vers
|
+ ObserverType* operator->() const; |
+ ObserverType& operator*() const; |
+ |
private: |
- WeakPtr<ObserverListBase<ObserverType>> list_; |
+ size_t GetNonNullIndex() const; |
+ |
+ size_t checked_max_index() const { |
+ return std::min(max_index_, list_->observers_.size()); |
+ } |
+ WeakPtr<ContainerType> list_; |
size_t index_; |
size_t max_index_; |
}; |
+ using Iterator = Iter<ObserverListBase<ObserverType>>; |
+ |
+ using iterator = Iter<ObserverListBase<ObserverType>>; |
+ iterator begin() { return iterator(this); } |
+ iterator end() { return iterator(); } |
+ |
+ using const_iterator = Iter<const ObserverListBase<ObserverType>>; |
+ const_iterator begin() const { 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) {} |
@@ -113,7 +155,8 @@ class ObserverListBase |
protected: |
size_t size() const { return observers_.size(); } |
- void Compact(); |
+ // Defragments the list despite const. |
+ void Compact() const; |
private: |
friend class ObserverListThreadSafe<ObserverType>; |
@@ -121,18 +164,24 @@ class ObserverListBase |
typedef std::vector<ObserverType*> ListType; |
ListType observers_; |
- int notify_depth_; |
+ mutable 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_(), max_index_() {} |
+ |
+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()) { |
@@ -140,21 +189,95 @@ ObserverListBase<ObserverType>::Iterator::Iterator( |
} |
template <class ObserverType> |
-ObserverListBase<ObserverType>::Iterator::~Iterator() { |
+template <class ContainerType> |
+ObserverListBase<ObserverType>::Iter<ContainerType>::~Iter() { |
if (list_.get() && --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 { |
+ return GetCurrent() != other.GetCurrent(); |
+} |
+ |
+template <class ObserverType> |
+template <class ContainerType> |
+typename ObserverListBase<ObserverType>::template Iter<ContainerType>& |
+ ObserverListBase<ObserverType>::Iter<ContainerType>::operator++() { |
+ Advance(); |
+ return *this; |
+} |
+ |
+template <class ObserverType> |
+template <class ContainerType> |
+typename ObserverListBase<ObserverType>::template Iter<ContainerType> |
+ ObserverListBase<ObserverType>::Iter<ContainerType>::operator++(int) { |
+ Iter previous(*this); |
+ Advance(); |
+ return previous; |
+} |
+ |
+template <class ObserverType> |
+template <class ContainerType> |
+ObserverType* ObserverListBase<ObserverType>::Iter<ContainerType>::operator->() |
+ const { |
+ return GetCurrent(); |
+} |
+ |
+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_]) |
- ++index_; |
- return index_ < max_index ? observers[index_++] : nullptr; |
+ size_t index = GetNonNullIndex(); |
+ return index < checked_max_index() ? list_->observers_[index] : nullptr; |
+} |
+ |
+template <class ObserverType> |
+template <class ContainerType> |
+size_t ObserverListBase<ObserverType>::Iter<ContainerType>::GetNonNullIndex() |
+ const { |
+ size_t index = index_; |
+ size_t max_index = checked_max_index(); |
+ while (index < max_index && !list_->observers_[index]) |
+ ++index; |
+ return index; |
+} |
+ |
+template <class ObserverType> |
+template <class ContainerType> |
+void ObserverListBase<ObserverType>::Iter<ContainerType>::Advance() { |
+ if (!list_) |
+ return; |
+ |
+ ++index_; |
+ index_ = GetNonNullIndex(); |
+} |
+ |
+template <class ObserverType> |
+template <class ContainerType> |
+ObserverType* ObserverListBase<ObserverType>::Iter<ContainerType>::GetNext() { |
+ if (!list_) |
+ return nullptr; |
+ |
+ ObserverType* current = GetCurrent(); |
+ |
+ index_ = GetNonNullIndex(); |
+ ++index_; |
+ |
+ return current; |
} |
template <class ObserverType> |
@@ -204,10 +327,10 @@ void ObserverListBase<ObserverType>::Clear() { |
} |
template <class ObserverType> |
-void ObserverListBase<ObserverType>::Compact() { |
- observers_.erase( |
- std::remove(observers_.begin(), observers_.end(), nullptr), |
- observers_.end()); |
+void ObserverListBase<ObserverType>::Compact() const { |
+ auto& observers = const_cast<ListType&>(observers_); |
+ observers.erase(std::remove(observers.begin(), observers.end(), nullptr), |
+ observers.end()); |
} |
template <class ObserverType, bool check_empty = false> |