observer_list.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. // Copyright (c) 2011 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.
  4. #ifndef BASE_OBSERVER_LIST_H_
  5. #define BASE_OBSERVER_LIST_H_
  6. #include <stddef.h>
  7. #include <algorithm>
  8. #include <iterator>
  9. #include <limits>
  10. #include <utility>
  11. #include <vector>
  12. #include "base/check_op.h"
  13. #include "base/gtest_prod_util.h"
  14. #include "base/notreached.h"
  15. #include "base/observer_list_internal.h"
  16. #include "base/sequence_checker.h"
  17. #include "base/stl_util.h"
  18. ///////////////////////////////////////////////////////////////////////////////
  19. //
  20. // OVERVIEW:
  21. //
  22. // A list of observers. Unlike a standard vector or list, this container can
  23. // be modified during iteration without invalidating the iterator. So, it
  24. // safely handles the case of an observer removing itself or other observers
  25. // from the list while observers are being notified.
  26. //
  27. //
  28. // WARNING:
  29. //
  30. // ObserverList is not thread-compatible. Iterating on the same ObserverList
  31. // simultaneously in different threads is not safe, even when the ObserverList
  32. // itself is not modified.
  33. //
  34. // For a thread-safe observer list, see ObserverListThreadSafe.
  35. //
  36. //
  37. // TYPICAL USAGE:
  38. //
  39. // class MyWidget {
  40. // public:
  41. // ...
  42. //
  43. // class Observer : public base::CheckedObserver {
  44. // public:
  45. // virtual void OnFoo(MyWidget* w) = 0;
  46. // virtual void OnBar(MyWidget* w, int x, int y) = 0;
  47. // };
  48. //
  49. // void AddObserver(Observer* obs) {
  50. // observers_.AddObserver(obs);
  51. // }
  52. //
  53. // void RemoveObserver(Observer* obs) {
  54. // observers_.RemoveObserver(obs);
  55. // }
  56. //
  57. // void NotifyFoo() {
  58. // for (Observer& obs : observers_)
  59. // obs.OnFoo(this);
  60. // }
  61. //
  62. // void NotifyBar(int x, int y) {
  63. // for (Observer& obs : observers_)
  64. // obs.OnBar(this, x, y);
  65. // }
  66. //
  67. // private:
  68. // base::ObserverList<Observer> observers_;
  69. // };
  70. //
  71. //
  72. ///////////////////////////////////////////////////////////////////////////////
  73. namespace base {
  74. // Enumeration of which observers are notified by ObserverList.
  75. enum class ObserverListPolicy {
  76. // Specifies that any observers added during notification are notified.
  77. // This is the default policy if no policy is provided to the constructor.
  78. ALL,
  79. // Specifies that observers added while sending out notification are not
  80. // notified.
  81. EXISTING_ONLY,
  82. };
  83. // When check_empty is true, assert that the list is empty on destruction.
  84. // When allow_reentrancy is false, iterating throught the list while already in
  85. // the iteration loop will result in DCHECK failure.
  86. // TODO(oshima): Change the default to non reentrant. https://crbug.com/812109
  87. template <class ObserverType,
  88. bool check_empty = false,
  89. bool allow_reentrancy = true,
  90. class ObserverStorageType = internal::CheckedObserverAdapter>
  91. class ObserverList {
  92. public:
  93. // Allow declaring an ObserverList<...>::Unchecked that replaces the default
  94. // ObserverStorageType to use raw pointers. This is required to support legacy
  95. // observers that do not inherit from CheckedObserver. The majority of new
  96. // code should not use this, but it may be suited for performance-critical
  97. // situations to avoid overheads of a CHECK(). Note the type can't be chosen
  98. // based on ObserverType's definition because ObserverLists are often declared
  99. // in headers using a forward-declare of ObserverType.
  100. using Unchecked = ObserverList<ObserverType,
  101. check_empty,
  102. allow_reentrancy,
  103. internal::UncheckedObserverAdapter>;
  104. // An iterator class that can be used to access the list of observers.
  105. class Iter {
  106. public:
  107. using iterator_category = std::forward_iterator_tag;
  108. using value_type = ObserverType;
  109. using difference_type = ptrdiff_t;
  110. using pointer = ObserverType*;
  111. using reference = ObserverType&;
  112. Iter() : index_(0), max_index_(0) {}
  113. explicit Iter(const ObserverList* list)
  114. : list_(const_cast<ObserverList*>(list)),
  115. index_(0),
  116. max_index_(list->policy_ == ObserverListPolicy::ALL
  117. ? std::numeric_limits<size_t>::max()
  118. : list->observers_.size()) {
  119. DCHECK(list);
  120. DCHECK(allow_reentrancy || list_.IsOnlyRemainingNode());
  121. // Bind to this sequence when creating the first iterator.
  122. DCHECK_CALLED_ON_VALID_SEQUENCE(list_->iteration_sequence_checker_);
  123. EnsureValidIndex();
  124. }
  125. ~Iter() {
  126. if (list_.IsOnlyRemainingNode())
  127. list_->Compact();
  128. }
  129. Iter(const Iter& other)
  130. : index_(other.index_), max_index_(other.max_index_) {
  131. if (other.list_)
  132. list_.SetList(other.list_.get());
  133. }
  134. Iter& operator=(const Iter& other) {
  135. if (&other == this)
  136. return *this;
  137. if (list_.IsOnlyRemainingNode())
  138. list_->Compact();
  139. list_.Invalidate();
  140. if (other.list_)
  141. list_.SetList(other.list_.get());
  142. index_ = other.index_;
  143. max_index_ = other.max_index_;
  144. return *this;
  145. }
  146. bool operator==(const Iter& other) const {
  147. return (is_end() && other.is_end()) ||
  148. (list_.get() == other.list_.get() && index_ == other.index_);
  149. }
  150. bool operator!=(const Iter& other) const { return !(*this == other); }
  151. Iter& operator++() {
  152. if (list_) {
  153. ++index_;
  154. EnsureValidIndex();
  155. }
  156. return *this;
  157. }
  158. Iter operator++(int) {
  159. Iter it(*this);
  160. ++(*this);
  161. return it;
  162. }
  163. ObserverType* operator->() const {
  164. ObserverType* const current = GetCurrent();
  165. DCHECK(current);
  166. return current;
  167. }
  168. ObserverType& operator*() const {
  169. ObserverType* const current = GetCurrent();
  170. DCHECK(current);
  171. return *current;
  172. }
  173. private:
  174. friend class ObserverListTestBase;
  175. ObserverType* GetCurrent() const {
  176. DCHECK(list_);
  177. DCHECK_LT(index_, clamped_max_index());
  178. return ObserverStorageType::template Get<ObserverType>(
  179. list_->observers_[index_]);
  180. }
  181. void EnsureValidIndex() {
  182. DCHECK(list_);
  183. const size_t max_index = clamped_max_index();
  184. while (index_ < max_index &&
  185. list_->observers_[index_].IsMarkedForRemoval()) {
  186. ++index_;
  187. }
  188. }
  189. size_t clamped_max_index() const {
  190. return std::min(max_index_, list_->observers_.size());
  191. }
  192. bool is_end() const { return !list_ || index_ == clamped_max_index(); }
  193. // Lightweight weak pointer to the ObserverList.
  194. internal::WeakLinkNode<ObserverList> list_;
  195. // When initially constructed and each time the iterator is incremented,
  196. // |index_| is guaranteed to point to a non-null index if the iterator
  197. // has not reached the end of the ObserverList.
  198. size_t index_;
  199. size_t max_index_;
  200. };
  201. using iterator = Iter;
  202. using const_iterator = Iter;
  203. using value_type = ObserverType;
  204. const_iterator begin() const {
  205. // An optimization: do not involve weak pointers for empty list.
  206. return observers_.empty() ? const_iterator() : const_iterator(this);
  207. }
  208. const_iterator end() const { return const_iterator(); }
  209. explicit ObserverList(ObserverListPolicy policy = ObserverListPolicy::ALL)
  210. : policy_(policy) {
  211. // Sequence checks only apply when iterators are live.
  212. DETACH_FROM_SEQUENCE(iteration_sequence_checker_);
  213. }
  214. ObserverList(const ObserverList&) = delete;
  215. ObserverList& operator=(const ObserverList&) = delete;
  216. ~ObserverList() {
  217. // If there are live iterators, ensure destruction is thread-safe.
  218. if (!live_iterators_.empty())
  219. DCHECK_CALLED_ON_VALID_SEQUENCE(iteration_sequence_checker_);
  220. while (!live_iterators_.empty())
  221. live_iterators_.head()->value()->Invalidate();
  222. if (check_empty) {
  223. Compact();
  224. DCHECK(observers_.empty());
  225. }
  226. }
  227. // Add an observer to this list. An observer should not be added to the same
  228. // list more than once.
  229. //
  230. // Precondition: obs != nullptr
  231. // Precondition: !HasObserver(obs)
  232. void AddObserver(ObserverType* obs) {
  233. DCHECK(obs);
  234. if (HasObserver(obs)) {
  235. NOTREACHED() << "Observers can only be added once!";
  236. return;
  237. }
  238. observers_.emplace_back(ObserverStorageType(obs));
  239. }
  240. // Removes the given observer from this list. Does nothing if this observer is
  241. // not in this list.
  242. void RemoveObserver(const ObserverType* obs) {
  243. DCHECK(obs);
  244. const auto it =
  245. std::find_if(observers_.begin(), observers_.end(),
  246. [obs](const auto& o) { return o.IsEqual(obs); });
  247. if (it == observers_.end())
  248. return;
  249. if (live_iterators_.empty()) {
  250. observers_.erase(it);
  251. } else {
  252. DCHECK_CALLED_ON_VALID_SEQUENCE(iteration_sequence_checker_);
  253. it->MarkForRemoval();
  254. }
  255. }
  256. // Determine whether a particular observer is in the list.
  257. bool HasObserver(const ObserverType* obs) const {
  258. // Client code passing null could be confused by the treatment of observers
  259. // removed mid-iteration. TODO(https://crbug.com/876588): This should
  260. // probably DCHECK, but some client code currently does pass null.
  261. if (obs == nullptr)
  262. return false;
  263. return std::find_if(observers_.begin(), observers_.end(),
  264. [obs](const auto& o) { return o.IsEqual(obs); }) !=
  265. observers_.end();
  266. }
  267. // Removes all the observers from this list.
  268. void Clear() {
  269. if (live_iterators_.empty()) {
  270. observers_.clear();
  271. } else {
  272. DCHECK_CALLED_ON_VALID_SEQUENCE(iteration_sequence_checker_);
  273. for (auto& observer : observers_)
  274. observer.MarkForRemoval();
  275. }
  276. }
  277. bool might_have_observers() const { return !observers_.empty(); }
  278. private:
  279. friend class internal::WeakLinkNode<ObserverList>;
  280. // Compacts list of observers by removing those marked for removal.
  281. void Compact() {
  282. // Detach whenever the last iterator is destroyed. Detaching is safe because
  283. // Compact() is only ever called when the last iterator is destroyed.
  284. DETACH_FROM_SEQUENCE(iteration_sequence_checker_);
  285. EraseIf(observers_, [](const auto& o) { return o.IsMarkedForRemoval(); });
  286. }
  287. std::vector<ObserverStorageType> observers_;
  288. base::LinkedList<internal::WeakLinkNode<ObserverList>> live_iterators_;
  289. const ObserverListPolicy policy_;
  290. SEQUENCE_CHECKER(iteration_sequence_checker_);
  291. };
  292. template <class ObserverType, bool check_empty = false>
  293. using ReentrantObserverList = ObserverList<ObserverType, check_empty, true>;
  294. } // namespace base
  295. #endif // BASE_OBSERVER_LIST_H_