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 } 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 192 template <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 [[ 200 template <> 201 class CallbackList<void(void)> 202 : public internal::CallbackListBase<Callback<void(void)> > { 203 ]] $else [[ 204 template <$for ARG , [[typename A$(ARG)]]> 205 class 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