Forgot a .h file.
[chromium-blink-merge.git] / base / observer_list.h
blob52571dff17eed7e7529a96a7ebb2454423e04cde
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 <vector>
9 #include <algorithm>
11 #include "base/basictypes.h"
12 #include "base/logging.h"
14 ///////////////////////////////////////////////////////////////////////////////
16 // OVERVIEW:
18 // A container for a list of observers. Unlike a normal STL vector or list,
19 // this container can be modified during iteration without invalidating the
20 // iterator. So, it safely handles the case of an observer removing itself
21 // or other observers from the list while observers are being notified.
23 // TYPICAL USAGE:
25 // class MyWidget {
26 // public:
27 // ...
29 // class Observer {
30 // public:
31 // virtual void OnFoo(MyWidget* w) = 0;
32 // virtual void OnBar(MyWidget* w, int x, int y) = 0;
33 // };
35 // void AddObserver(Observer* obs) {
36 // observer_list_.AddObserver(obs);
37 // }
39 // void RemoveObserver(Observer* obs) {
40 // observer_list_.RemoveObserver(obs);
41 // }
43 // void NotifyFoo() {
44 // FOR_EACH_OBSERVER(Observer, observer_list_, OnFoo(this));
45 // }
47 // void NotifyBar(int x, int y) {
48 // FOR_EACH_OBSERVER(Observer, observer_list_, OnBar(this, x, y));
49 // }
51 // private:
52 // ObserverList<Observer> observer_list_;
53 // };
55 ///////////////////////////////////////////////////////////////////////////////
57 template <class ObserverType, bool check_empty = false>
58 class ObserverList {
59 public:
60 ObserverList() : notify_depth_(0) {}
61 ~ObserverList() {
62 // When check_empty is true, assert that the list is empty on destruction.
63 if (check_empty) {
64 Compact();
65 DCHECK_EQ(observers_.size(), 0U);
69 // Add an observer to the list.
70 void AddObserver(ObserverType* obs) {
71 DCHECK(find(observers_.begin(), observers_.end(), obs) == observers_.end())
72 << "Observers can only be added once!";
73 observers_.push_back(obs);
76 // Remove an observer from the list.
77 void RemoveObserver(ObserverType* obs) {
78 typename ListType::iterator it =
79 std::find(observers_.begin(), observers_.end(), obs);
80 if (it != observers_.end()) {
81 if (notify_depth_) {
82 *it = 0;
83 } else {
84 observers_.erase(it);
89 size_t size() const {
90 return observers_.size();
93 ObserverType* GetElementAt(int index) const {
94 return observers_[index];
97 // An iterator class that can be used to access the list of observers. See
98 // also the FOREACH_OBSERVER macro defined below.
99 class Iterator {
100 public:
101 Iterator(const ObserverList<ObserverType>& list) : list_(list), index_(0) {
102 ++list_.notify_depth_;
105 ~Iterator() {
106 if (--list_.notify_depth_ == 0)
107 list_.Compact();
110 ObserverType* GetNext() {
111 ListType& observers = list_.observers_;
112 // Advance if the current element is null
113 while (index_ < observers.size() && !observers[index_])
114 ++index_;
115 return index_ < observers.size() ? observers[index_++] : NULL;
118 private:
119 const ObserverList<ObserverType>& list_;
120 size_t index_;
123 private:
124 typedef std::vector<ObserverType*> ListType;
126 void Compact() const {
127 typename ListType::iterator it = observers_.begin();
128 while (it != observers_.end()) {
129 if (*it) {
130 ++it;
131 } else {
132 it = observers_.erase(it);
137 // These are marked mutable to facilitate having NotifyAll be const.
138 mutable ListType observers_;
139 mutable int notify_depth_;
141 friend class ObserverList::Iterator;
143 DISALLOW_EVIL_CONSTRUCTORS(ObserverList);
146 #define FOR_EACH_OBSERVER(ObserverType, observer_list, func) \
147 do { \
148 ObserverList<ObserverType>::Iterator it(observer_list); \
149 ObserverType* obs; \
150 while ((obs = it.GetNext()) != NULL) \
151 obs->func; \
152 } while (0)
154 #endif // BASE_OBSERVER_LIST_H__