Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(58)

Side by Side Diff: base/observer_list.h

Issue 8919: Adds the ability for ObserverList to not notify observers added during... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 12 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | base/observer_list_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « no previous file | base/observer_list_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698