1*6777b538SAndroid Build Coastguard Worker // Copyright 2013 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_CALLBACK_LIST_H_ 6*6777b538SAndroid Build Coastguard Worker #define BASE_CALLBACK_LIST_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <list> 9*6777b538SAndroid Build Coastguard Worker #include <memory> 10*6777b538SAndroid Build Coastguard Worker #include <utility> 11*6777b538SAndroid Build Coastguard Worker 12*6777b538SAndroid Build Coastguard Worker #include "base/auto_reset.h" 13*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h" 14*6777b538SAndroid Build Coastguard Worker #include "base/check.h" 15*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h" 16*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback.h" 17*6777b538SAndroid Build Coastguard Worker #include "base/memory/weak_ptr.h" 18*6777b538SAndroid Build Coastguard Worker #include "base/ranges/algorithm.h" 19*6777b538SAndroid Build Coastguard Worker #include "base/types/is_instantiation.h" 20*6777b538SAndroid Build Coastguard Worker 21*6777b538SAndroid Build Coastguard Worker // OVERVIEW: 22*6777b538SAndroid Build Coastguard Worker // 23*6777b538SAndroid Build Coastguard Worker // A container for a list of callbacks. Provides callers the ability to manually 24*6777b538SAndroid Build Coastguard Worker // or automatically unregister callbacks at any time, including during callback 25*6777b538SAndroid Build Coastguard Worker // notification. 26*6777b538SAndroid Build Coastguard Worker // 27*6777b538SAndroid Build Coastguard Worker // TYPICAL USAGE: 28*6777b538SAndroid Build Coastguard Worker // 29*6777b538SAndroid Build Coastguard Worker // class MyWidget { 30*6777b538SAndroid Build Coastguard Worker // public: 31*6777b538SAndroid Build Coastguard Worker // using CallbackList = base::RepeatingCallbackList<void(const Foo&)>; 32*6777b538SAndroid Build Coastguard Worker // 33*6777b538SAndroid Build Coastguard Worker // // Registers |cb| to be called whenever NotifyFoo() is executed. 34*6777b538SAndroid Build Coastguard Worker // CallbackListSubscription RegisterCallback(CallbackList::CallbackType cb) { 35*6777b538SAndroid Build Coastguard Worker // return callback_list_.Add(std::move(cb)); 36*6777b538SAndroid Build Coastguard Worker // } 37*6777b538SAndroid Build Coastguard Worker // 38*6777b538SAndroid Build Coastguard Worker // private: 39*6777b538SAndroid Build Coastguard Worker // // Calls all registered callbacks, with |foo| as the supplied arg. 40*6777b538SAndroid Build Coastguard Worker // void NotifyFoo(const Foo& foo) { 41*6777b538SAndroid Build Coastguard Worker // callback_list_.Notify(foo); 42*6777b538SAndroid Build Coastguard Worker // } 43*6777b538SAndroid Build Coastguard Worker // 44*6777b538SAndroid Build Coastguard Worker // CallbackList callback_list_; 45*6777b538SAndroid Build Coastguard Worker // }; 46*6777b538SAndroid Build Coastguard Worker // 47*6777b538SAndroid Build Coastguard Worker // 48*6777b538SAndroid Build Coastguard Worker // class MyWidgetListener { 49*6777b538SAndroid Build Coastguard Worker // private: 50*6777b538SAndroid Build Coastguard Worker // void OnFoo(const Foo& foo) { 51*6777b538SAndroid Build Coastguard Worker // // Called whenever MyWidget::NotifyFoo() is executed, unless 52*6777b538SAndroid Build Coastguard Worker // // |foo_subscription_| has been destroyed. 53*6777b538SAndroid Build Coastguard Worker // } 54*6777b538SAndroid Build Coastguard Worker // 55*6777b538SAndroid Build Coastguard Worker // // Automatically deregisters the callback when deleted (e.g. in 56*6777b538SAndroid Build Coastguard Worker // // ~MyWidgetListener()). Unretained(this) is safe here since the 57*6777b538SAndroid Build Coastguard Worker // // ScopedClosureRunner does not outlive |this|. 58*6777b538SAndroid Build Coastguard Worker // CallbackListSubscription foo_subscription_ = 59*6777b538SAndroid Build Coastguard Worker // MyWidget::Get()->RegisterCallback( 60*6777b538SAndroid Build Coastguard Worker // base::BindRepeating(&MyWidgetListener::OnFoo, 61*6777b538SAndroid Build Coastguard Worker // base::Unretained(this))); 62*6777b538SAndroid Build Coastguard Worker // }; 63*6777b538SAndroid Build Coastguard Worker // 64*6777b538SAndroid Build Coastguard Worker // UNSUPPORTED: 65*6777b538SAndroid Build Coastguard Worker // 66*6777b538SAndroid Build Coastguard Worker // * Destroying the CallbackList during callback notification. 67*6777b538SAndroid Build Coastguard Worker // 68*6777b538SAndroid Build Coastguard Worker // This is possible to support, but not currently necessary. 69*6777b538SAndroid Build Coastguard Worker 70*6777b538SAndroid Build Coastguard Worker namespace base { 71*6777b538SAndroid Build Coastguard Worker namespace internal { 72*6777b538SAndroid Build Coastguard Worker template <typename CallbackListImpl> 73*6777b538SAndroid Build Coastguard Worker class CallbackListBase; 74*6777b538SAndroid Build Coastguard Worker } // namespace internal 75*6777b538SAndroid Build Coastguard Worker 76*6777b538SAndroid Build Coastguard Worker template <typename Signature> 77*6777b538SAndroid Build Coastguard Worker class OnceCallbackList; 78*6777b538SAndroid Build Coastguard Worker 79*6777b538SAndroid Build Coastguard Worker template <typename Signature> 80*6777b538SAndroid Build Coastguard Worker class RepeatingCallbackList; 81*6777b538SAndroid Build Coastguard Worker 82*6777b538SAndroid Build Coastguard Worker // A trimmed-down version of ScopedClosureRunner that can be used to guarantee a 83*6777b538SAndroid Build Coastguard Worker // closure is run on destruction. This is designed to be used by 84*6777b538SAndroid Build Coastguard Worker // CallbackListBase to run CancelCallback() when this subscription dies; 85*6777b538SAndroid Build Coastguard Worker // consumers can avoid callbacks on dead objects by ensuring the subscription 86*6777b538SAndroid Build Coastguard Worker // returned by CallbackListBase::Add() does not outlive the bound object in the 87*6777b538SAndroid Build Coastguard Worker // callback. A typical way to do this is to bind a callback to a member function 88*6777b538SAndroid Build Coastguard Worker // on `this` and store the returned subscription as a member variable. 89*6777b538SAndroid Build Coastguard Worker class [[nodiscard]] BASE_EXPORT CallbackListSubscription { 90*6777b538SAndroid Build Coastguard Worker public: 91*6777b538SAndroid Build Coastguard Worker CallbackListSubscription(); 92*6777b538SAndroid Build Coastguard Worker CallbackListSubscription(CallbackListSubscription&& subscription); 93*6777b538SAndroid Build Coastguard Worker CallbackListSubscription& operator=(CallbackListSubscription&& subscription); 94*6777b538SAndroid Build Coastguard Worker ~CallbackListSubscription(); 95*6777b538SAndroid Build Coastguard Worker 96*6777b538SAndroid Build Coastguard Worker explicit operator bool() const { return !!closure_; } 97*6777b538SAndroid Build Coastguard Worker 98*6777b538SAndroid Build Coastguard Worker private: 99*6777b538SAndroid Build Coastguard Worker template <typename T> 100*6777b538SAndroid Build Coastguard Worker friend class internal::CallbackListBase; 101*6777b538SAndroid Build Coastguard Worker 102*6777b538SAndroid Build Coastguard Worker explicit CallbackListSubscription(base::OnceClosure closure); 103*6777b538SAndroid Build Coastguard Worker 104*6777b538SAndroid Build Coastguard Worker void Run(); 105*6777b538SAndroid Build Coastguard Worker 106*6777b538SAndroid Build Coastguard Worker OnceClosure closure_; 107*6777b538SAndroid Build Coastguard Worker }; 108*6777b538SAndroid Build Coastguard Worker 109*6777b538SAndroid Build Coastguard Worker namespace internal { 110*6777b538SAndroid Build Coastguard Worker 111*6777b538SAndroid Build Coastguard Worker // A traits class to break circular type dependencies between CallbackListBase 112*6777b538SAndroid Build Coastguard Worker // and its subclasses. 113*6777b538SAndroid Build Coastguard Worker template <typename CallbackList> 114*6777b538SAndroid Build Coastguard Worker struct CallbackListTraits; 115*6777b538SAndroid Build Coastguard Worker 116*6777b538SAndroid Build Coastguard Worker // NOTE: It's important that Callbacks provide iterator stability when items are 117*6777b538SAndroid Build Coastguard Worker // added to the end, so e.g. a std::vector<> is not suitable here. 118*6777b538SAndroid Build Coastguard Worker template <typename Signature> 119*6777b538SAndroid Build Coastguard Worker struct CallbackListTraits<OnceCallbackList<Signature>> { 120*6777b538SAndroid Build Coastguard Worker using CallbackType = OnceCallback<Signature>; 121*6777b538SAndroid Build Coastguard Worker using Callbacks = std::list<CallbackType>; 122*6777b538SAndroid Build Coastguard Worker }; 123*6777b538SAndroid Build Coastguard Worker template <typename Signature> 124*6777b538SAndroid Build Coastguard Worker struct CallbackListTraits<RepeatingCallbackList<Signature>> { 125*6777b538SAndroid Build Coastguard Worker using CallbackType = RepeatingCallback<Signature>; 126*6777b538SAndroid Build Coastguard Worker using Callbacks = std::list<CallbackType>; 127*6777b538SAndroid Build Coastguard Worker }; 128*6777b538SAndroid Build Coastguard Worker 129*6777b538SAndroid Build Coastguard Worker template <typename CallbackListImpl> 130*6777b538SAndroid Build Coastguard Worker class CallbackListBase { 131*6777b538SAndroid Build Coastguard Worker public: 132*6777b538SAndroid Build Coastguard Worker using CallbackType = 133*6777b538SAndroid Build Coastguard Worker typename CallbackListTraits<CallbackListImpl>::CallbackType; 134*6777b538SAndroid Build Coastguard Worker 135*6777b538SAndroid Build Coastguard Worker // TODO(crbug.com/1103086): Update references to use this directly and by 136*6777b538SAndroid Build Coastguard Worker // value, then remove. 137*6777b538SAndroid Build Coastguard Worker using Subscription = CallbackListSubscription; 138*6777b538SAndroid Build Coastguard Worker 139*6777b538SAndroid Build Coastguard Worker CallbackListBase() = default; 140*6777b538SAndroid Build Coastguard Worker CallbackListBase(const CallbackListBase&) = delete; 141*6777b538SAndroid Build Coastguard Worker CallbackListBase& operator=(const CallbackListBase&) = delete; 142*6777b538SAndroid Build Coastguard Worker 143*6777b538SAndroid Build Coastguard Worker ~CallbackListBase() { 144*6777b538SAndroid Build Coastguard Worker // Destroying the list during iteration is unsupported and will cause a UAF. 145*6777b538SAndroid Build Coastguard Worker CHECK(!iterating_); 146*6777b538SAndroid Build Coastguard Worker } 147*6777b538SAndroid Build Coastguard Worker 148*6777b538SAndroid Build Coastguard Worker // Registers |cb| for future notifications. Returns a CallbackListSubscription 149*6777b538SAndroid Build Coastguard Worker // whose destruction will cancel |cb|. 150*6777b538SAndroid Build Coastguard Worker [[nodiscard]] CallbackListSubscription Add(CallbackType cb) { 151*6777b538SAndroid Build Coastguard Worker DCHECK(!cb.is_null()); 152*6777b538SAndroid Build Coastguard Worker return CallbackListSubscription(base::BindOnce( 153*6777b538SAndroid Build Coastguard Worker &CallbackListBase::CancelCallback, weak_ptr_factory_.GetWeakPtr(), 154*6777b538SAndroid Build Coastguard Worker callbacks_.insert(callbacks_.end(), std::move(cb)))); 155*6777b538SAndroid Build Coastguard Worker } 156*6777b538SAndroid Build Coastguard Worker 157*6777b538SAndroid Build Coastguard Worker // Registers |cb| for future notifications. Provides no way for the caller to 158*6777b538SAndroid Build Coastguard Worker // cancel, so this is only safe for cases where the callback is guaranteed to 159*6777b538SAndroid Build Coastguard Worker // live at least as long as this list (e.g. if it's bound on the same object 160*6777b538SAndroid Build Coastguard Worker // that owns the list). 161*6777b538SAndroid Build Coastguard Worker // TODO(pkasting): Attempt to use Add() instead and see if callers can relax 162*6777b538SAndroid Build Coastguard Worker // other lifetime/ordering mechanisms as a result. 163*6777b538SAndroid Build Coastguard Worker void AddUnsafe(CallbackType cb) { 164*6777b538SAndroid Build Coastguard Worker DCHECK(!cb.is_null()); 165*6777b538SAndroid Build Coastguard Worker callbacks_.push_back(std::move(cb)); 166*6777b538SAndroid Build Coastguard Worker } 167*6777b538SAndroid Build Coastguard Worker 168*6777b538SAndroid Build Coastguard Worker // Registers |removal_callback| to be run after elements are removed from the 169*6777b538SAndroid Build Coastguard Worker // list of registered callbacks. 170*6777b538SAndroid Build Coastguard Worker void set_removal_callback(const RepeatingClosure& removal_callback) { 171*6777b538SAndroid Build Coastguard Worker removal_callback_ = removal_callback; 172*6777b538SAndroid Build Coastguard Worker } 173*6777b538SAndroid Build Coastguard Worker 174*6777b538SAndroid Build Coastguard Worker // Returns whether the list of registered callbacks is empty (from an external 175*6777b538SAndroid Build Coastguard Worker // perspective -- meaning no remaining callbacks are live). 176*6777b538SAndroid Build Coastguard Worker bool empty() const { 177*6777b538SAndroid Build Coastguard Worker return ranges::all_of( 178*6777b538SAndroid Build Coastguard Worker callbacks_, [](const auto& callback) { return callback.is_null(); }); 179*6777b538SAndroid Build Coastguard Worker } 180*6777b538SAndroid Build Coastguard Worker 181*6777b538SAndroid Build Coastguard Worker // Calls all registered callbacks that are not canceled beforehand. If any 182*6777b538SAndroid Build Coastguard Worker // callbacks are unregistered, notifies any registered removal callback at the 183*6777b538SAndroid Build Coastguard Worker // end. 184*6777b538SAndroid Build Coastguard Worker // 185*6777b538SAndroid Build Coastguard Worker // Arguments must be copyable, since they must be supplied to all callbacks. 186*6777b538SAndroid Build Coastguard Worker // Move-only types would be destructively modified by passing them to the 187*6777b538SAndroid Build Coastguard Worker // first callback and not reach subsequent callbacks as intended. 188*6777b538SAndroid Build Coastguard Worker // 189*6777b538SAndroid Build Coastguard Worker // Notify() may be called re-entrantly, in which case the nested call 190*6777b538SAndroid Build Coastguard Worker // completes before the outer one continues. Callbacks are only ever added at 191*6777b538SAndroid Build Coastguard Worker // the end and canceled callbacks are not pruned from the list until the 192*6777b538SAndroid Build Coastguard Worker // outermost iteration completes, so existing iterators should never be 193*6777b538SAndroid Build Coastguard Worker // invalidated. However, this does mean that a callback added during a nested 194*6777b538SAndroid Build Coastguard Worker // call can be notified by outer calls -- meaning it will be notified about 195*6777b538SAndroid Build Coastguard Worker // things that happened before it was added -- if its subscription outlives 196*6777b538SAndroid Build Coastguard Worker // the reentrant Notify() call. 197*6777b538SAndroid Build Coastguard Worker template <typename... RunArgs> 198*6777b538SAndroid Build Coastguard Worker void Notify(RunArgs&&... args) { 199*6777b538SAndroid Build Coastguard Worker if (empty()) 200*6777b538SAndroid Build Coastguard Worker return; // Nothing to do. 201*6777b538SAndroid Build Coastguard Worker 202*6777b538SAndroid Build Coastguard Worker { 203*6777b538SAndroid Build Coastguard Worker AutoReset<bool> iterating(&iterating_, true); 204*6777b538SAndroid Build Coastguard Worker 205*6777b538SAndroid Build Coastguard Worker // Skip any callbacks that are canceled during iteration. 206*6777b538SAndroid Build Coastguard Worker // NOTE: Since RunCallback() may call Add(), it's not safe to cache the 207*6777b538SAndroid Build Coastguard Worker // value of callbacks_.end() across loop iterations. 208*6777b538SAndroid Build Coastguard Worker const auto next_valid = [this](const auto it) { 209*6777b538SAndroid Build Coastguard Worker return std::find_if_not(it, callbacks_.end(), [](const auto& callback) { 210*6777b538SAndroid Build Coastguard Worker return callback.is_null(); 211*6777b538SAndroid Build Coastguard Worker }); 212*6777b538SAndroid Build Coastguard Worker }; 213*6777b538SAndroid Build Coastguard Worker for (auto it = next_valid(callbacks_.begin()); it != callbacks_.end(); 214*6777b538SAndroid Build Coastguard Worker it = next_valid(it)) 215*6777b538SAndroid Build Coastguard Worker // NOTE: Intentionally does not call std::forward<RunArgs>(args)..., 216*6777b538SAndroid Build Coastguard Worker // since that would allow move-only arguments. 217*6777b538SAndroid Build Coastguard Worker static_cast<CallbackListImpl*>(this)->RunCallback(it++, args...); 218*6777b538SAndroid Build Coastguard Worker } 219*6777b538SAndroid Build Coastguard Worker 220*6777b538SAndroid Build Coastguard Worker // Re-entrant invocations shouldn't prune anything from the list. This can 221*6777b538SAndroid Build Coastguard Worker // invalidate iterators from underneath higher call frames. It's safe to 222*6777b538SAndroid Build Coastguard Worker // simply do nothing, since the outermost frame will continue through here 223*6777b538SAndroid Build Coastguard Worker // and prune all null callbacks below. 224*6777b538SAndroid Build Coastguard Worker if (iterating_) 225*6777b538SAndroid Build Coastguard Worker return; 226*6777b538SAndroid Build Coastguard Worker 227*6777b538SAndroid Build Coastguard Worker // Any null callbacks remaining in the list were canceled due to 228*6777b538SAndroid Build Coastguard Worker // Subscription destruction during iteration, and can safely be erased now. 229*6777b538SAndroid Build Coastguard Worker const size_t erased_callbacks = 230*6777b538SAndroid Build Coastguard Worker std::erase_if(callbacks_, [](const auto& cb) { return cb.is_null(); }); 231*6777b538SAndroid Build Coastguard Worker 232*6777b538SAndroid Build Coastguard Worker // Run |removal_callback_| if any callbacks were canceled. Note that we 233*6777b538SAndroid Build Coastguard Worker // cannot simply compare list sizes before and after iterating, since 234*6777b538SAndroid Build Coastguard Worker // notification may result in Add()ing new callbacks as well as canceling 235*6777b538SAndroid Build Coastguard Worker // them. Also note that if this is a OnceCallbackList, the OnceCallbacks 236*6777b538SAndroid Build Coastguard Worker // that were executed above have all been removed regardless of whether 237*6777b538SAndroid Build Coastguard Worker // they're counted in |erased_callbacks_|. 238*6777b538SAndroid Build Coastguard Worker if (removal_callback_ && 239*6777b538SAndroid Build Coastguard Worker (erased_callbacks || is_instantiation<OnceCallback, CallbackType>)) { 240*6777b538SAndroid Build Coastguard Worker removal_callback_.Run(); // May delete |this|! 241*6777b538SAndroid Build Coastguard Worker } 242*6777b538SAndroid Build Coastguard Worker } 243*6777b538SAndroid Build Coastguard Worker 244*6777b538SAndroid Build Coastguard Worker protected: 245*6777b538SAndroid Build Coastguard Worker using Callbacks = typename CallbackListTraits<CallbackListImpl>::Callbacks; 246*6777b538SAndroid Build Coastguard Worker 247*6777b538SAndroid Build Coastguard Worker // Holds non-null callbacks, which will be called during Notify(). 248*6777b538SAndroid Build Coastguard Worker Callbacks callbacks_; 249*6777b538SAndroid Build Coastguard Worker 250*6777b538SAndroid Build Coastguard Worker private: 251*6777b538SAndroid Build Coastguard Worker // Cancels the callback pointed to by |it|, which is guaranteed to be valid. 252*6777b538SAndroid Build Coastguard Worker void CancelCallback(const typename Callbacks::iterator& it) { 253*6777b538SAndroid Build Coastguard Worker if (static_cast<CallbackListImpl*>(this)->CancelNullCallback(it)) 254*6777b538SAndroid Build Coastguard Worker return; 255*6777b538SAndroid Build Coastguard Worker 256*6777b538SAndroid Build Coastguard Worker if (iterating_) { 257*6777b538SAndroid Build Coastguard Worker // Calling erase() here is unsafe, since the loop in Notify() may be 258*6777b538SAndroid Build Coastguard Worker // referencing this same iterator, e.g. if adjacent callbacks' 259*6777b538SAndroid Build Coastguard Worker // Subscriptions are both destroyed when the first one is Run(). Just 260*6777b538SAndroid Build Coastguard Worker // reset the callback and let Notify() clean it up at the end. 261*6777b538SAndroid Build Coastguard Worker it->Reset(); 262*6777b538SAndroid Build Coastguard Worker } else { 263*6777b538SAndroid Build Coastguard Worker callbacks_.erase(it); 264*6777b538SAndroid Build Coastguard Worker if (removal_callback_) 265*6777b538SAndroid Build Coastguard Worker removal_callback_.Run(); // May delete |this|! 266*6777b538SAndroid Build Coastguard Worker } 267*6777b538SAndroid Build Coastguard Worker } 268*6777b538SAndroid Build Coastguard Worker 269*6777b538SAndroid Build Coastguard Worker // Set while Notify() is traversing |callbacks_|. Used primarily to avoid 270*6777b538SAndroid Build Coastguard Worker // invalidating iterators that may be in use. 271*6777b538SAndroid Build Coastguard Worker bool iterating_ = false; 272*6777b538SAndroid Build Coastguard Worker 273*6777b538SAndroid Build Coastguard Worker // Called after elements are removed from |callbacks_|. 274*6777b538SAndroid Build Coastguard Worker RepeatingClosure removal_callback_; 275*6777b538SAndroid Build Coastguard Worker 276*6777b538SAndroid Build Coastguard Worker WeakPtrFactory<CallbackListBase> weak_ptr_factory_{this}; 277*6777b538SAndroid Build Coastguard Worker }; 278*6777b538SAndroid Build Coastguard Worker 279*6777b538SAndroid Build Coastguard Worker } // namespace internal 280*6777b538SAndroid Build Coastguard Worker 281*6777b538SAndroid Build Coastguard Worker template <typename Signature> 282*6777b538SAndroid Build Coastguard Worker class OnceCallbackList 283*6777b538SAndroid Build Coastguard Worker : public internal::CallbackListBase<OnceCallbackList<Signature>> { 284*6777b538SAndroid Build Coastguard Worker private: 285*6777b538SAndroid Build Coastguard Worker friend internal::CallbackListBase<OnceCallbackList>; 286*6777b538SAndroid Build Coastguard Worker using Traits = internal::CallbackListTraits<OnceCallbackList>; 287*6777b538SAndroid Build Coastguard Worker 288*6777b538SAndroid Build Coastguard Worker // Runs the current callback, which may cancel it or any other callbacks. 289*6777b538SAndroid Build Coastguard Worker template <typename... RunArgs> 290*6777b538SAndroid Build Coastguard Worker void RunCallback(typename Traits::Callbacks::iterator it, RunArgs&&... args) { 291*6777b538SAndroid Build Coastguard Worker // OnceCallbacks still have Subscriptions with outstanding iterators; 292*6777b538SAndroid Build Coastguard Worker // splice() removes them from |callbacks_| without invalidating those. 293*6777b538SAndroid Build Coastguard Worker null_callbacks_.splice(null_callbacks_.end(), this->callbacks_, it); 294*6777b538SAndroid Build Coastguard Worker 295*6777b538SAndroid Build Coastguard Worker // NOTE: Intentionally does not call std::forward<RunArgs>(args)...; see 296*6777b538SAndroid Build Coastguard Worker // comments in Notify(). 297*6777b538SAndroid Build Coastguard Worker std::move(*it).Run(args...); 298*6777b538SAndroid Build Coastguard Worker } 299*6777b538SAndroid Build Coastguard Worker 300*6777b538SAndroid Build Coastguard Worker // If |it| refers to an already-canceled callback, does any necessary cleanup 301*6777b538SAndroid Build Coastguard Worker // and returns true. Otherwise returns false. 302*6777b538SAndroid Build Coastguard Worker bool CancelNullCallback(const typename Traits::Callbacks::iterator& it) { 303*6777b538SAndroid Build Coastguard Worker if (it->is_null()) { 304*6777b538SAndroid Build Coastguard Worker null_callbacks_.erase(it); 305*6777b538SAndroid Build Coastguard Worker return true; 306*6777b538SAndroid Build Coastguard Worker } 307*6777b538SAndroid Build Coastguard Worker return false; 308*6777b538SAndroid Build Coastguard Worker } 309*6777b538SAndroid Build Coastguard Worker 310*6777b538SAndroid Build Coastguard Worker // Holds null callbacks whose Subscriptions are still alive, so the 311*6777b538SAndroid Build Coastguard Worker // Subscriptions will still contain valid iterators. Only needed for 312*6777b538SAndroid Build Coastguard Worker // OnceCallbacks, since RepeatingCallbacks are not canceled except by 313*6777b538SAndroid Build Coastguard Worker // Subscription destruction. 314*6777b538SAndroid Build Coastguard Worker typename Traits::Callbacks null_callbacks_; 315*6777b538SAndroid Build Coastguard Worker }; 316*6777b538SAndroid Build Coastguard Worker 317*6777b538SAndroid Build Coastguard Worker template <typename Signature> 318*6777b538SAndroid Build Coastguard Worker class RepeatingCallbackList 319*6777b538SAndroid Build Coastguard Worker : public internal::CallbackListBase<RepeatingCallbackList<Signature>> { 320*6777b538SAndroid Build Coastguard Worker private: 321*6777b538SAndroid Build Coastguard Worker friend internal::CallbackListBase<RepeatingCallbackList>; 322*6777b538SAndroid Build Coastguard Worker using Traits = internal::CallbackListTraits<RepeatingCallbackList>; 323*6777b538SAndroid Build Coastguard Worker // Runs the current callback, which may cancel it or any other callbacks. 324*6777b538SAndroid Build Coastguard Worker template <typename... RunArgs> 325*6777b538SAndroid Build Coastguard Worker void RunCallback(typename Traits::Callbacks::iterator it, RunArgs&&... args) { 326*6777b538SAndroid Build Coastguard Worker // NOTE: Intentionally does not call std::forward<RunArgs>(args)...; see 327*6777b538SAndroid Build Coastguard Worker // comments in Notify(). 328*6777b538SAndroid Build Coastguard Worker it->Run(args...); 329*6777b538SAndroid Build Coastguard Worker } 330*6777b538SAndroid Build Coastguard Worker 331*6777b538SAndroid Build Coastguard Worker // If |it| refers to an already-canceled callback, does any necessary cleanup 332*6777b538SAndroid Build Coastguard Worker // and returns true. Otherwise returns false. 333*6777b538SAndroid Build Coastguard Worker bool CancelNullCallback(const typename Traits::Callbacks::iterator& it) { 334*6777b538SAndroid Build Coastguard Worker // Because at most one Subscription can point to a given callback, and 335*6777b538SAndroid Build Coastguard Worker // RepeatingCallbacks are only reset by CancelCallback(), no one should be 336*6777b538SAndroid Build Coastguard Worker // able to request cancellation of a canceled RepeatingCallback. 337*6777b538SAndroid Build Coastguard Worker DCHECK(!it->is_null()); 338*6777b538SAndroid Build Coastguard Worker return false; 339*6777b538SAndroid Build Coastguard Worker } 340*6777b538SAndroid Build Coastguard Worker }; 341*6777b538SAndroid Build Coastguard Worker 342*6777b538SAndroid Build Coastguard Worker // Syntactic sugar to parallel that used for {Once,Repeating}Callbacks. 343*6777b538SAndroid Build Coastguard Worker using OnceClosureList = OnceCallbackList<void()>; 344*6777b538SAndroid Build Coastguard Worker using RepeatingClosureList = RepeatingCallbackList<void()>; 345*6777b538SAndroid Build Coastguard Worker 346*6777b538SAndroid Build Coastguard Worker } // namespace base 347*6777b538SAndroid Build Coastguard Worker 348*6777b538SAndroid Build Coastguard Worker #endif // BASE_CALLBACK_LIST_H_ 349