1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/base/observer_list.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,184 @@ 1.4 +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#ifndef BASE_OBSERVER_LIST_H__ 1.9 +#define BASE_OBSERVER_LIST_H__ 1.10 + 1.11 +#include <algorithm> 1.12 +#include <limits> 1.13 +#include <vector> 1.14 + 1.15 +#include "base/basictypes.h" 1.16 +#include "base/logging.h" 1.17 + 1.18 +#if defined(ANDROID) && defined(_STLP_STD_NAME) 1.19 +using _STLP_STD_NAME::find; 1.20 +#endif 1.21 + 1.22 +namespace base { 1.23 + 1.24 +/////////////////////////////////////////////////////////////////////////////// 1.25 +// 1.26 +// OVERVIEW: 1.27 +// 1.28 +// A container for a list of observers. Unlike a normal STL vector or list, 1.29 +// this container can be modified during iteration without invalidating the 1.30 +// iterator. So, it safely handles the case of an observer removing itself 1.31 +// or other observers from the list while observers are being notified. 1.32 +// 1.33 +// TYPICAL USAGE: 1.34 +// 1.35 +// class MyWidget { 1.36 +// public: 1.37 +// ... 1.38 +// 1.39 +// class Observer { 1.40 +// public: 1.41 +// virtual void OnFoo(MyWidget* w) = 0; 1.42 +// virtual void OnBar(MyWidget* w, int x, int y) = 0; 1.43 +// }; 1.44 +// 1.45 +// void AddObserver(Observer* obs) { 1.46 +// observer_list_.AddObserver(obs); 1.47 +// } 1.48 +// 1.49 +// void RemoveObserver(Observer* obs) { 1.50 +// observer_list_.RemoveObserver(obs); 1.51 +// } 1.52 +// 1.53 +// void NotifyFoo() { 1.54 +// FOR_EACH_OBSERVER(Observer, observer_list_, OnFoo(this)); 1.55 +// } 1.56 +// 1.57 +// void NotifyBar(int x, int y) { 1.58 +// FOR_EACH_OBSERVER(Observer, observer_list_, OnBar(this, x, y)); 1.59 +// } 1.60 +// 1.61 +// private: 1.62 +// ObserverList<Observer> observer_list_; 1.63 +// }; 1.64 +// 1.65 +// 1.66 +/////////////////////////////////////////////////////////////////////////////// 1.67 + 1.68 +template <class ObserverType, bool check_empty = false> 1.69 +class ObserverList { 1.70 + public: 1.71 + // Enumeration of which observers are notified. 1.72 + enum NotificationType { 1.73 + // Specifies that any observers added during notification are notified. 1.74 + // This is the default type if non type is provided to the constructor. 1.75 + NOTIFY_ALL, 1.76 + 1.77 + // Specifies that observers added while sending out notification are not 1.78 + // notified. 1.79 + NOTIFY_EXISTING_ONLY 1.80 + }; 1.81 + 1.82 + ObserverList() : notify_depth_(0), type_(NOTIFY_ALL) {} 1.83 + ObserverList(NotificationType type) : notify_depth_(0), type_(type) {} 1.84 + ~ObserverList() { 1.85 + // When check_empty is true, assert that the list is empty on destruction. 1.86 + if (check_empty) { 1.87 + Compact(); 1.88 + DCHECK_EQ(observers_.size(), 0U); 1.89 + } 1.90 + } 1.91 + 1.92 + // Add an observer to the list. 1.93 + void AddObserver(ObserverType* obs) { 1.94 + DCHECK(find(observers_.begin(), observers_.end(), obs) == observers_.end()) 1.95 + << "Observers can only be added once!"; 1.96 + observers_.push_back(obs); 1.97 + } 1.98 + 1.99 + // Remove an observer from the list. 1.100 + void RemoveObserver(ObserverType* obs) { 1.101 + typename ListType::iterator it = 1.102 + std::find(observers_.begin(), observers_.end(), obs); 1.103 + if (it != observers_.end()) { 1.104 + if (notify_depth_) { 1.105 + *it = 0; 1.106 + } else { 1.107 + observers_.erase(it); 1.108 + } 1.109 + } 1.110 + } 1.111 + 1.112 + size_t size() const { 1.113 + return observers_.size(); 1.114 + } 1.115 + 1.116 + ObserverType* GetElementAt(int index) const { 1.117 + return observers_[index]; 1.118 + } 1.119 + 1.120 + // An iterator class that can be used to access the list of observers. See 1.121 + // also the FOREACH_OBSERVER macro defined below. 1.122 + class Iterator { 1.123 + public: 1.124 + Iterator(const ObserverList<ObserverType>& list) 1.125 + : list_(list), 1.126 + index_(0), 1.127 + max_index_(list.type_ == NOTIFY_ALL ? 1.128 + std::numeric_limits<size_t>::max() : 1.129 + list.observers_.size()) { 1.130 + ++list_.notify_depth_; 1.131 + } 1.132 + 1.133 + ~Iterator() { 1.134 + if (--list_.notify_depth_ == 0) 1.135 + list_.Compact(); 1.136 + } 1.137 + 1.138 + ObserverType* GetNext() { 1.139 + ListType& observers = list_.observers_; 1.140 + // Advance if the current element is null 1.141 + size_t max_index = std::min(max_index_, observers.size()); 1.142 + while (index_ < max_index && !observers[index_]) 1.143 + ++index_; 1.144 + return index_ < max_index ? observers[index_++] : NULL; 1.145 + } 1.146 + 1.147 + private: 1.148 + const ObserverList<ObserverType>& list_; 1.149 + size_t index_; 1.150 + size_t max_index_; 1.151 + }; 1.152 + 1.153 + private: 1.154 + typedef std::vector<ObserverType*> ListType; 1.155 + 1.156 + void Compact() const { 1.157 + typename ListType::iterator it = observers_.begin(); 1.158 + while (it != observers_.end()) { 1.159 + if (*it) { 1.160 + ++it; 1.161 + } else { 1.162 + it = observers_.erase(it); 1.163 + } 1.164 + } 1.165 + } 1.166 + 1.167 + // These are marked mutable to facilitate having NotifyAll be const. 1.168 + mutable ListType observers_; 1.169 + mutable int notify_depth_; 1.170 + NotificationType type_; 1.171 + 1.172 + friend class ObserverList::Iterator; 1.173 + 1.174 + DISALLOW_EVIL_CONSTRUCTORS(ObserverList); 1.175 +}; 1.176 + 1.177 +} // namespace base 1.178 + 1.179 +#define FOR_EACH_OBSERVER(ObserverType, observer_list, func) \ 1.180 + do { \ 1.181 + base::ObserverList<ObserverType>::Iterator it(observer_list); \ 1.182 + ObserverType* obs; \ 1.183 + while ((obs = it.GetNext()) != NULL) \ 1.184 + obs->func; \ 1.185 + } while (0) 1.186 + 1.187 +#endif // BASE_OBSERVER_LIST_H__