xref: /aosp_15_r20/external/cronet/base/callback_list.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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