1$$ This is a pump file for generating file templates. Pump is a python 2$$ script that is part of the Google Test suite of utilities. Description 3$$ can be found here: 4$$ 5$$ http://code.google.com/p/googletest/wiki/PumpManual 6$$ 7 8$$ See comment for MAX_ARITY in base/bind.h.pump. 9$var MAX_ARITY = 7 10 11// Copyright 2013 The Chromium Authors. All rights reserved. 12// Use of this source code is governed by a BSD-style license that can be 13// found in the LICENSE file. 14 15#ifndef BASE_CALLBACK_LIST_H_ 16#define BASE_CALLBACK_LIST_H_ 17 18#include <list> 19 20#include "base/basictypes.h" 21#include "base/callback.h" 22#include "base/callback_internal.h" 23#include "base/compiler_specific.h" 24#include "base/logging.h" 25#include "base/memory/scoped_ptr.h" 26 27// OVERVIEW: 28// 29// A container for a list of callbacks. Unlike a normal STL vector or list, 30// this container can be modified during iteration without invalidating the 31// iterator. It safely handles the case of a callback removing itself 32// or another callback from the list while callbacks are being run. 33// 34// TYPICAL USAGE: 35// 36// class MyWidget { 37// public: 38// ... 39// 40// typedef base::Callback<void(const Foo&)> OnFooCallback; 41// 42// scoped_ptr<base::CallbackList<void(const Foo&)>::Subscription> 43// RegisterCallback(const OnFooCallback& cb) { 44// return callback_list_.Add(cb); 45// } 46// 47// private: 48// void NotifyFoo(const Foo& foo) { 49// callback_list_.Notify(foo); 50// } 51// 52// base::CallbackList<void(const Foo&)> callback_list_; 53// 54// DISALLOW_COPY_AND_ASSIGN(MyWidget); 55// }; 56// 57// 58// class MyWidgetListener { 59// public: 60// MyWidgetListener::MyWidgetListener() { 61// foo_subscription_ = MyWidget::GetCurrent()->RegisterCallback( 62// base::Bind(&MyWidgetListener::OnFoo, this))); 63// } 64// 65// MyWidgetListener::~MyWidgetListener() { 66// // Subscription gets deleted automatically and will deregister 67// // the callback in the process. 68// } 69// 70// private: 71// void OnFoo(const Foo& foo) { 72// // Do something. 73// } 74// 75// scoped_ptr<base::CallbackList<void(const Foo&)>::Subscription> 76// foo_subscription_; 77// 78// DISALLOW_COPY_AND_ASSIGN(MyWidgetListener); 79// }; 80 81namespace base { 82 83namespace internal { 84 85template <typename CallbackType> 86class CallbackListBase { 87 public: 88 class Subscription { 89 public: 90 Subscription(CallbackListBase<CallbackType>* list, 91 typename std::list<CallbackType>::iterator iter) 92 : list_(list), 93 iter_(iter) { 94 } 95 96 ~Subscription() { 97 if (list_->active_iterator_count_) { 98 iter_->Reset(); 99 } else { 100 list_->callbacks_.erase(iter_); 101 if (!list_->removal_callback_.is_null()) 102 list_->removal_callback_.Run(); 103 } 104 } 105 106 private: 107 CallbackListBase<CallbackType>* list_; 108 typename std::list<CallbackType>::iterator iter_; 109 110 DISALLOW_COPY_AND_ASSIGN(Subscription); 111 }; 112 113 // Add a callback to the list. The callback will remain registered until the 114 // returned Subscription is destroyed, which must occur before the 115 // CallbackList is destroyed. 116 scoped_ptr<Subscription> Add(const CallbackType& cb) WARN_UNUSED_RESULT { 117 DCHECK(!cb.is_null()); 118 return scoped_ptr<Subscription>( 119 new Subscription(this, callbacks_.insert(callbacks_.end(), cb))); 120 } 121 122 // Sets a callback which will be run when a subscription list is changed. 123 void set_removal_callback(const Closure& callback) { 124 removal_callback_ = callback; 125 } 126 127 // Returns true if there are no subscriptions. This is only valid to call when 128 // not looping through the list. 129 bool empty() { 130 DCHECK_EQ(0, active_iterator_count_); 131 return callbacks_.empty(); 132 } 133 134 protected: 135 // An iterator class that can be used to access the list of callbacks. 136 class Iterator { 137 public: 138 explicit Iterator(CallbackListBase<CallbackType>* list) 139 : list_(list), 140 list_iter_(list_->callbacks_.begin()) { 141 ++list_->active_iterator_count_; 142 } 143 144 Iterator(const Iterator& iter) 145 : list_(iter.list_), 146 list_iter_(iter.list_iter_) { 147 ++list_->active_iterator_count_; 148 } 149 150 ~Iterator() { 151 if (list_ && --list_->active_iterator_count_ == 0) { 152 list_->Compact(); 153 } 154 } 155 156 CallbackType* GetNext() { 157 while ((list_iter_ != list_->callbacks_.end()) && list_iter_->is_null()) 158 ++list_iter_; 159 160 CallbackType* cb = NULL; 161 if (list_iter_ != list_->callbacks_.end()) { 162 cb = &(*list_iter_); 163 ++list_iter_; 164 } 165 return cb; 166 } 167 168 private: 169 CallbackListBase<CallbackType>* list_; 170 typename std::list<CallbackType>::iterator list_iter_; 171 }; 172 173 CallbackListBase() : active_iterator_count_(0) {} 174 175 ~CallbackListBase() { 176 DCHECK_EQ(0, active_iterator_count_); 177 DCHECK_EQ(0U, callbacks_.size()); 178 } 179 180 // Returns an instance of a CallbackListBase::Iterator which can be used 181 // to run callbacks. 182 Iterator GetIterator() { 183 return Iterator(this); 184 } 185 186 // Compact the list: remove any entries which were NULLed out during 187 // iteration. 188 void Compact() { 189 typename std::list<CallbackType>::iterator it = callbacks_.begin(); 190 bool updated = false; 191 while (it != callbacks_.end()) { 192 if ((*it).is_null()) { 193 updated = true; 194 it = callbacks_.erase(it); 195 } else { 196 ++it; 197 } 198 199 if (updated && !removal_callback_.is_null()) 200 removal_callback_.Run(); 201 } 202 } 203 204 private: 205 std::list<CallbackType> callbacks_; 206 int active_iterator_count_; 207 Closure removal_callback_; 208 209 DISALLOW_COPY_AND_ASSIGN(CallbackListBase); 210}; 211 212} // namespace internal 213 214template <typename Sig> class CallbackList; 215 216 217$range ARITY 0..MAX_ARITY 218$for ARITY [[ 219$range ARG 1..ARITY 220 221$if ARITY == 0 [[ 222template <> 223class CallbackList<void(void)> 224 : public internal::CallbackListBase<Callback<void(void)> > { 225]] $else [[ 226template <$for ARG , [[typename A$(ARG)]]> 227class CallbackList<void($for ARG , [[A$(ARG)]])> 228 : public internal::CallbackListBase<Callback<void($for ARG , [[A$(ARG)]])> > { 229]] 230 231 public: 232$if ARITY == 0 [[ 233 234 typedef Callback<void(void)> CallbackType; 235]] $else [[ 236 237 typedef Callback<void($for ARG , [[A$(ARG)]])> CallbackType; 238]] 239 240 241 CallbackList() {} 242 243 void Notify($for ARG , 244 [[typename internal::CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) { 245$if ARITY == 0 [[ 246 247 internal::CallbackListBase<CallbackType>::Iterator it = 248 this->GetIterator(); 249]] $else [[ 250 251 typename internal::CallbackListBase<CallbackType>::Iterator it = 252 this->GetIterator(); 253]] 254 255 CallbackType* cb; 256 while ((cb = it.GetNext()) != NULL) { 257 cb->Run($for ARG , [[a$(ARG)]]); 258 } 259 } 260 261 private: 262 DISALLOW_COPY_AND_ASSIGN(CallbackList); 263}; 264 265 266]] $$ for ARITY 267} // namespace base 268 269#endif // BASE_CALLBACK_LIST_H_ 270