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 81 namespace base { 82 83 namespace internal { 84 85 template <typename CallbackType> 86 class 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 214 template <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 [[ 222 template <> 223 class CallbackList<void(void)> 224 : public internal::CallbackListBase<Callback<void(void)> > { 225 ]] $else [[ 226 template <$for ARG , [[typename A$(ARG)]]> 227 class 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