OLD | NEW |
---|---|
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef BASE_OBSERVER_LIST_H__ | 5 #ifndef BASE_OBSERVER_LIST_H__ |
6 #define BASE_OBSERVER_LIST_H__ | 6 #define BASE_OBSERVER_LIST_H__ |
7 | 7 |
8 #include <algorithm> | |
9 #include <limits> | |
8 #include <vector> | 10 #include <vector> |
9 #include <algorithm> | |
10 | 11 |
11 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
12 #include "base/logging.h" | 13 #include "base/logging.h" |
13 | 14 |
14 /////////////////////////////////////////////////////////////////////////////// | 15 /////////////////////////////////////////////////////////////////////////////// |
15 // | 16 // |
16 // OVERVIEW: | 17 // OVERVIEW: |
17 // | 18 // |
18 // A container for a list of observers. Unlike a normal STL vector or list, | 19 // 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 // this container can be modified during iteration without invalidating the |
(...skipping 25 matching lines...) Expand all Loading... | |
45 // } | 46 // } |
46 // | 47 // |
47 // void NotifyBar(int x, int y) { | 48 // void NotifyBar(int x, int y) { |
48 // FOR_EACH_OBSERVER(Observer, observer_list_, OnBar(this, x, y)); | 49 // FOR_EACH_OBSERVER(Observer, observer_list_, OnBar(this, x, y)); |
49 // } | 50 // } |
50 // | 51 // |
51 // private: | 52 // private: |
52 // ObserverList<Observer> observer_list_; | 53 // ObserverList<Observer> observer_list_; |
53 // }; | 54 // }; |
54 // | 55 // |
56 // | |
55 /////////////////////////////////////////////////////////////////////////////// | 57 /////////////////////////////////////////////////////////////////////////////// |
56 | 58 |
57 template <class ObserverType, bool check_empty = false> | 59 template <class ObserverType, bool check_empty = false> |
58 class ObserverList { | 60 class ObserverList { |
59 public: | 61 public: |
60 ObserverList() : notify_depth_(0) {} | 62 // Enumeration of which observers are notified. |
63 enum NotificationType { | |
64 // Specifies that any observers added during notification are notified. | |
65 // This is the default type if non type is provided to the constructor. | |
66 NOTIFY_ALL, | |
67 | |
68 // Specifies that observers added while sending out notification are not | |
69 // notified. | |
70 NOTIFY_EXISTING_ONLY | |
71 }; | |
darin (slow to review)
2008/10/30 20:12:50
nit: add a newline below here.
| |
72 ObserverList() : notify_depth_(0), type_(NOTIFY_ALL) {} | |
73 ObserverList(NotificationType type) : notify_depth_(0), type_(type) {} | |
61 ~ObserverList() { | 74 ~ObserverList() { |
62 // When check_empty is true, assert that the list is empty on destruction. | 75 // When check_empty is true, assert that the list is empty on destruction. |
63 if (check_empty) { | 76 if (check_empty) { |
64 Compact(); | 77 Compact(); |
65 DCHECK_EQ(observers_.size(), 0U); | 78 DCHECK_EQ(observers_.size(), 0U); |
66 } | 79 } |
67 } | 80 } |
68 | 81 |
69 // Add an observer to the list. | 82 // Add an observer to the list. |
70 void AddObserver(ObserverType* obs) { | 83 void AddObserver(ObserverType* obs) { |
(...skipping 20 matching lines...) Expand all Loading... | |
91 } | 104 } |
92 | 105 |
93 ObserverType* GetElementAt(int index) const { | 106 ObserverType* GetElementAt(int index) const { |
94 return observers_[index]; | 107 return observers_[index]; |
95 } | 108 } |
96 | 109 |
97 // An iterator class that can be used to access the list of observers. See | 110 // An iterator class that can be used to access the list of observers. See |
98 // also the FOREACH_OBSERVER macro defined below. | 111 // also the FOREACH_OBSERVER macro defined below. |
99 class Iterator { | 112 class Iterator { |
100 public: | 113 public: |
101 Iterator(const ObserverList<ObserverType>& list) : list_(list), index_(0) { | 114 Iterator(const ObserverList<ObserverType>& list) |
115 : list_(list), | |
116 index_(0), | |
117 max_index_(list.type_ == NOTIFY_ALL ? | |
118 std::numeric_limits<size_t>::max() : | |
119 list.observers_.size()) { | |
102 ++list_.notify_depth_; | 120 ++list_.notify_depth_; |
103 } | 121 } |
104 | 122 |
105 ~Iterator() { | 123 ~Iterator() { |
106 if (--list_.notify_depth_ == 0) | 124 if (--list_.notify_depth_ == 0) |
107 list_.Compact(); | 125 list_.Compact(); |
108 } | 126 } |
109 | 127 |
110 ObserverType* GetNext() { | 128 ObserverType* GetNext() { |
111 ListType& observers = list_.observers_; | 129 ListType& observers = list_.observers_; |
112 // Advance if the current element is null | 130 // Advance if the current element is null |
113 while (index_ < observers.size() && !observers[index_]) | 131 size_t max_index = std::min(max_index_, observers.size()); |
132 while (index_ < max_index && !observers[index_]) | |
114 ++index_; | 133 ++index_; |
115 return index_ < observers.size() ? observers[index_++] : NULL; | 134 return index_ < max_index ? observers[index_++] : NULL; |
116 } | 135 } |
117 | 136 |
118 private: | 137 private: |
119 const ObserverList<ObserverType>& list_; | 138 const ObserverList<ObserverType>& list_; |
120 size_t index_; | 139 size_t index_; |
140 size_t max_index_; | |
121 }; | 141 }; |
122 | 142 |
123 private: | 143 private: |
124 typedef std::vector<ObserverType*> ListType; | 144 typedef std::vector<ObserverType*> ListType; |
125 | 145 |
126 void Compact() const { | 146 void Compact() const { |
127 typename ListType::iterator it = observers_.begin(); | 147 typename ListType::iterator it = observers_.begin(); |
128 while (it != observers_.end()) { | 148 while (it != observers_.end()) { |
129 if (*it) { | 149 if (*it) { |
130 ++it; | 150 ++it; |
131 } else { | 151 } else { |
132 it = observers_.erase(it); | 152 it = observers_.erase(it); |
133 } | 153 } |
134 } | 154 } |
135 } | 155 } |
136 | 156 |
137 // These are marked mutable to facilitate having NotifyAll be const. | 157 // These are marked mutable to facilitate having NotifyAll be const. |
138 mutable ListType observers_; | 158 mutable ListType observers_; |
139 mutable int notify_depth_; | 159 mutable int notify_depth_; |
160 NotificationType type_; | |
140 | 161 |
141 friend class ObserverList::Iterator; | 162 friend class ObserverList::Iterator; |
142 | 163 |
143 DISALLOW_EVIL_CONSTRUCTORS(ObserverList); | 164 DISALLOW_EVIL_CONSTRUCTORS(ObserverList); |
144 }; | 165 }; |
145 | 166 |
146 #define FOR_EACH_OBSERVER(ObserverType, observer_list, func) \ | 167 #define FOR_EACH_OBSERVER(ObserverType, observer_list, func) \ |
147 do { \ | 168 do { \ |
148 ObserverList<ObserverType>::Iterator it(observer_list); \ | 169 ObserverList<ObserverType>::Iterator it(observer_list); \ |
149 ObserverType* obs; \ | 170 ObserverType* obs; \ |
150 while ((obs = it.GetNext()) != NULL) \ | 171 while ((obs = it.GetNext()) != NULL) \ |
151 obs->func; \ | 172 obs->func; \ |
152 } while (0) | 173 } while (0) |
153 | 174 |
154 #endif // BASE_OBSERVER_LIST_H__ | 175 #endif // BASE_OBSERVER_LIST_H__ |
155 | 176 |
OLD | NEW |