Chromium Code Reviews| 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 |