1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/sandbox/chromium/base/observer_list.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,217 @@ 1.4 +// Copyright (c) 2011 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 +#include "base/memory/weak_ptr.h" 1.18 + 1.19 +/////////////////////////////////////////////////////////////////////////////// 1.20 +// 1.21 +// OVERVIEW: 1.22 +// 1.23 +// A container for a list of observers. Unlike a normal STL vector or list, 1.24 +// this container can be modified during iteration without invalidating the 1.25 +// iterator. So, it safely handles the case of an observer removing itself 1.26 +// or other observers from the list while observers are being notified. 1.27 +// 1.28 +// TYPICAL USAGE: 1.29 +// 1.30 +// class MyWidget { 1.31 +// public: 1.32 +// ... 1.33 +// 1.34 +// class Observer { 1.35 +// public: 1.36 +// virtual void OnFoo(MyWidget* w) = 0; 1.37 +// virtual void OnBar(MyWidget* w, int x, int y) = 0; 1.38 +// }; 1.39 +// 1.40 +// void AddObserver(Observer* obs) { 1.41 +// observer_list_.AddObserver(obs); 1.42 +// } 1.43 +// 1.44 +// void RemoveObserver(Observer* obs) { 1.45 +// observer_list_.RemoveObserver(obs); 1.46 +// } 1.47 +// 1.48 +// void NotifyFoo() { 1.49 +// FOR_EACH_OBSERVER(Observer, observer_list_, OnFoo(this)); 1.50 +// } 1.51 +// 1.52 +// void NotifyBar(int x, int y) { 1.53 +// FOR_EACH_OBSERVER(Observer, observer_list_, OnBar(this, x, y)); 1.54 +// } 1.55 +// 1.56 +// private: 1.57 +// ObserverList<Observer> observer_list_; 1.58 +// }; 1.59 +// 1.60 +// 1.61 +/////////////////////////////////////////////////////////////////////////////// 1.62 + 1.63 +template <typename ObserverType> 1.64 +class ObserverListThreadSafe; 1.65 + 1.66 +template <class ObserverType> 1.67 +class ObserverListBase 1.68 + : public base::SupportsWeakPtr<ObserverListBase<ObserverType> > { 1.69 + public: 1.70 + // Enumeration of which observers are notified. 1.71 + enum NotificationType { 1.72 + // Specifies that any observers added during notification are notified. 1.73 + // This is the default type if non type is provided to the constructor. 1.74 + NOTIFY_ALL, 1.75 + 1.76 + // Specifies that observers added while sending out notification are not 1.77 + // notified. 1.78 + NOTIFY_EXISTING_ONLY 1.79 + }; 1.80 + 1.81 + // An iterator class that can be used to access the list of observers. See 1.82 + // also the FOR_EACH_OBSERVER macro defined below. 1.83 + class Iterator { 1.84 + public: 1.85 + Iterator(ObserverListBase<ObserverType>& list) 1.86 + : list_(list.AsWeakPtr()), 1.87 + index_(0), 1.88 + max_index_(list.type_ == NOTIFY_ALL ? 1.89 + std::numeric_limits<size_t>::max() : 1.90 + list.observers_.size()) { 1.91 + ++list_->notify_depth_; 1.92 + } 1.93 + 1.94 + ~Iterator() { 1.95 + if (list_.get() && --list_->notify_depth_ == 0) 1.96 + list_->Compact(); 1.97 + } 1.98 + 1.99 + ObserverType* GetNext() { 1.100 + if (!list_.get()) 1.101 + return NULL; 1.102 + ListType& observers = list_->observers_; 1.103 + // Advance if the current element is null 1.104 + size_t max_index = std::min(max_index_, observers.size()); 1.105 + while (index_ < max_index && !observers[index_]) 1.106 + ++index_; 1.107 + return index_ < max_index ? observers[index_++] : NULL; 1.108 + } 1.109 + 1.110 + private: 1.111 + base::WeakPtr<ObserverListBase<ObserverType> > list_; 1.112 + size_t index_; 1.113 + size_t max_index_; 1.114 + }; 1.115 + 1.116 + ObserverListBase() : notify_depth_(0), type_(NOTIFY_ALL) {} 1.117 + explicit ObserverListBase(NotificationType type) 1.118 + : notify_depth_(0), type_(type) {} 1.119 + 1.120 + // Add an observer to the list. An observer should not be added to 1.121 + // the same list more than once. 1.122 + void AddObserver(ObserverType* obs) { 1.123 + if (std::find(observers_.begin(), observers_.end(), obs) 1.124 + != observers_.end()) { 1.125 + NOTREACHED() << "Observers can only be added once!"; 1.126 + return; 1.127 + } 1.128 + observers_.push_back(obs); 1.129 + } 1.130 + 1.131 + // Remove an observer from the list if it is in the list. 1.132 + void RemoveObserver(ObserverType* obs) { 1.133 + typename ListType::iterator it = 1.134 + std::find(observers_.begin(), observers_.end(), obs); 1.135 + if (it != observers_.end()) { 1.136 + if (notify_depth_) { 1.137 + *it = 0; 1.138 + } else { 1.139 + observers_.erase(it); 1.140 + } 1.141 + } 1.142 + } 1.143 + 1.144 + bool HasObserver(ObserverType* observer) const { 1.145 + for (size_t i = 0; i < observers_.size(); ++i) { 1.146 + if (observers_[i] == observer) 1.147 + return true; 1.148 + } 1.149 + return false; 1.150 + } 1.151 + 1.152 + void Clear() { 1.153 + if (notify_depth_) { 1.154 + for (typename ListType::iterator it = observers_.begin(); 1.155 + it != observers_.end(); ++it) { 1.156 + *it = 0; 1.157 + } 1.158 + } else { 1.159 + observers_.clear(); 1.160 + } 1.161 + } 1.162 + 1.163 + protected: 1.164 + size_t size() const { return observers_.size(); } 1.165 + 1.166 + void Compact() { 1.167 + observers_.erase( 1.168 + std::remove(observers_.begin(), observers_.end(), 1.169 + static_cast<ObserverType*>(NULL)), observers_.end()); 1.170 + } 1.171 + 1.172 + private: 1.173 + friend class ObserverListThreadSafe<ObserverType>; 1.174 + 1.175 + typedef std::vector<ObserverType*> ListType; 1.176 + 1.177 + ListType observers_; 1.178 + int notify_depth_; 1.179 + NotificationType type_; 1.180 + 1.181 + friend class ObserverListBase::Iterator; 1.182 + 1.183 + DISALLOW_COPY_AND_ASSIGN(ObserverListBase); 1.184 +}; 1.185 + 1.186 +template <class ObserverType, bool check_empty = false> 1.187 +class ObserverList : public ObserverListBase<ObserverType> { 1.188 + public: 1.189 + typedef typename ObserverListBase<ObserverType>::NotificationType 1.190 + NotificationType; 1.191 + 1.192 + ObserverList() {} 1.193 + explicit ObserverList(NotificationType type) 1.194 + : ObserverListBase<ObserverType>(type) {} 1.195 + 1.196 + ~ObserverList() { 1.197 + // When check_empty is true, assert that the list is empty on destruction. 1.198 + if (check_empty) { 1.199 + ObserverListBase<ObserverType>::Compact(); 1.200 + DCHECK_EQ(ObserverListBase<ObserverType>::size(), 0U); 1.201 + } 1.202 + } 1.203 + 1.204 + bool might_have_observers() const { 1.205 + return ObserverListBase<ObserverType>::size() != 0; 1.206 + } 1.207 +}; 1.208 + 1.209 +#define FOR_EACH_OBSERVER(ObserverType, observer_list, func) \ 1.210 + do { \ 1.211 + if ((observer_list).might_have_observers()) { \ 1.212 + ObserverListBase<ObserverType>::Iterator \ 1.213 + it_inside_observer_macro(observer_list); \ 1.214 + ObserverType* obs; \ 1.215 + while ((obs = it_inside_observer_macro.GetNext()) != NULL) \ 1.216 + obs->func; \ 1.217 + } \ 1.218 + } while (0) 1.219 + 1.220 +#endif // BASE_OBSERVER_LIST_H__