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 } 102 103 private: 104 CallbackListBase<CallbackType>* list_; 105 typename std::list<CallbackType>::iterator iter_; 106 107 DISALLOW_COPY_AND_ASSIGN(Subscription); 108 }; 109 110 // Add a callback to the list. The callback will remain registered until the 111 // returned Subscription is destroyed, which must occur before the 112 // CallbackList is destroyed. 113 scoped_ptr<Subscription> Add(const CallbackType& cb) WARN_UNUSED_RESULT { 114 DCHECK(!cb.is_null()); 115 return scoped_ptr<Subscription>( 116 new Subscription(this, callbacks_.insert(callbacks_.end(), cb))); 117 } 118 119 protected: 120 // An iterator class that can be used to access the list of callbacks. 121 class Iterator { 122 public: 123 explicit Iterator(CallbackListBase<CallbackType>* list) 124 : list_(list), 125 list_iter_(list_->callbacks_.begin()) { 126 ++list_->active_iterator_count_; 127 } 128 129 Iterator(const Iterator& iter) 130 : list_(iter.list_), 131 list_iter_(iter.list_iter_) { 132 ++list_->active_iterator_count_; 133 } 134 135 ~Iterator() { 136 if (list_ && --list_->active_iterator_count_ == 0) { 137 list_->Compact(); 138 } 139 } 140 141 CallbackType* GetNext() { 142 while ((list_iter_ != list_->callbacks_.end()) && list_iter_->is_null()) 143 ++list_iter_; 144 145 CallbackType* cb = NULL; 146 if (list_iter_ != list_->callbacks_.end()) { 147 cb = &(*list_iter_); 148 ++list_iter_; 149 } 150 return cb; 151 } 152 153 private: 154 CallbackListBase<CallbackType>* list_; 155 typename std::list<CallbackType>::iterator list_iter_; 156 }; 157 158 CallbackListBase() : active_iterator_count_(0) {} 159 160 ~CallbackListBase() { 161 DCHECK_EQ(0, active_iterator_count_); 162 DCHECK_EQ(0U, callbacks_.size()); 163 } 164 165 // Returns an instance of a CallbackListBase::Iterator which can be used 166 // to run callbacks. 167 Iterator GetIterator() { 168 return Iterator(this); 169 } 170 171 // Compact the list: remove any entries which were NULLed out during 172 // iteration. 173 void Compact() { 174 typename std::list<CallbackType>::iterator it = callbacks_.begin(); 175 while (it != callbacks_.end()) { 176 if ((*it).is_null()) 177 it = callbacks_.erase(it); 178 else 179 ++it; 180 } 181 } 182 183 private: 184 std::list<CallbackType> callbacks_; 185 int active_iterator_count_; 186 187 DISALLOW_COPY_AND_ASSIGN(CallbackListBase); 188}; 189 190} // namespace internal 191 192template <typename Sig> class CallbackList; 193 194 195$range ARITY 0..MAX_ARITY 196$for ARITY [[ 197$range ARG 1..ARITY 198 199$if ARITY == 0 [[ 200template <> 201class CallbackList<void(void)> 202 : public internal::CallbackListBase<Callback<void(void)> > { 203]] $else [[ 204template <$for ARG , [[typename A$(ARG)]]> 205class CallbackList<void($for ARG , [[A$(ARG)]])> 206 : public internal::CallbackListBase<Callback<void($for ARG , [[A$(ARG)]])> > { 207]] 208 209 public: 210$if ARITY == 0 [[ 211 212 typedef Callback<void(void)> CallbackType; 213]] $else [[ 214 215 typedef Callback<void($for ARG , [[A$(ARG)]])> CallbackType; 216]] 217 218 219 CallbackList() {} 220 221 void Notify($for ARG , 222 [[typename internal::CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) { 223$if ARITY == 0 [[ 224 225 internal::CallbackListBase<CallbackType>::Iterator it = 226 this->GetIterator(); 227]] $else [[ 228 229 typename internal::CallbackListBase<CallbackType>::Iterator it = 230 this->GetIterator(); 231]] 232 233 CallbackType* cb; 234 while ((cb = it.GetNext()) != NULL) { 235 cb->Run($for ARG , [[a$(ARG)]]); 236 } 237 } 238 239 private: 240 DISALLOW_COPY_AND_ASSIGN(CallbackList); 241}; 242 243 244]] $$ for ARITY 245} // namespace base 246 247#endif // BASE_CALLBACK_LIST_H_ 248