xref: /aosp_15_r20/external/cronet/base/cancelable_callback.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2011 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 // CancelableOnceCallback is a wrapper around OnceCallback that allows
6*6777b538SAndroid Build Coastguard Worker // cancellation of the callback. CanacelableRepeatingCallback is the same sort
7*6777b538SAndroid Build Coastguard Worker // of wrapper around RepeatingCallback. The wrapper takes a reference on the
8*6777b538SAndroid Build Coastguard Worker // wrapped callback until this object is destroyed or Reset()/Cancel() are
9*6777b538SAndroid Build Coastguard Worker // called.
10*6777b538SAndroid Build Coastguard Worker //
11*6777b538SAndroid Build Coastguard Worker // NOTE:
12*6777b538SAndroid Build Coastguard Worker //
13*6777b538SAndroid Build Coastguard Worker // Calling Cancel() brings the object back to its natural, default-constructed
14*6777b538SAndroid Build Coastguard Worker // state, i.e., callback() will return a null callback.
15*6777b538SAndroid Build Coastguard Worker //
16*6777b538SAndroid Build Coastguard Worker // THREAD-SAFETY:
17*6777b538SAndroid Build Coastguard Worker //
18*6777b538SAndroid Build Coastguard Worker // Cancelable callback objects must be created on, posted to, cancelled on, and
19*6777b538SAndroid Build Coastguard Worker // destroyed on the same SequencedTaskRunner. The wrapper returned by callback()
20*6777b538SAndroid Build Coastguard Worker // must also be run on this SequencedTaskRunner, but it may be destroyed on any
21*6777b538SAndroid Build Coastguard Worker // sequence; see comments on callback().
22*6777b538SAndroid Build Coastguard Worker //
23*6777b538SAndroid Build Coastguard Worker //
24*6777b538SAndroid Build Coastguard Worker // EXAMPLE USAGE:
25*6777b538SAndroid Build Coastguard Worker //
26*6777b538SAndroid Build Coastguard Worker // In the following example, the test is verifying that RunIntensiveTest()
27*6777b538SAndroid Build Coastguard Worker // Quit()s the message loop within 4 seconds. The cancelable callback is posted
28*6777b538SAndroid Build Coastguard Worker // to the message loop, the intensive test runs, the message loop is run,
29*6777b538SAndroid Build Coastguard Worker // then the callback is cancelled.
30*6777b538SAndroid Build Coastguard Worker //
31*6777b538SAndroid Build Coastguard Worker // RunLoop run_loop;
32*6777b538SAndroid Build Coastguard Worker //
33*6777b538SAndroid Build Coastguard Worker // void TimeoutCallback(const std::string& timeout_message) {
34*6777b538SAndroid Build Coastguard Worker //   FAIL() << timeout_message;
35*6777b538SAndroid Build Coastguard Worker //   run_loop.QuitWhenIdle();
36*6777b538SAndroid Build Coastguard Worker // }
37*6777b538SAndroid Build Coastguard Worker //
38*6777b538SAndroid Build Coastguard Worker // CancelableOnceClosure timeout(
39*6777b538SAndroid Build Coastguard Worker //     base::BindOnce(&TimeoutCallback, "Test timed out."));
40*6777b538SAndroid Build Coastguard Worker // SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
41*6777b538SAndroid Build Coastguard Worker //     FROM_HERE, timeout.callback(), Seconds(4));
42*6777b538SAndroid Build Coastguard Worker // RunIntensiveTest();
43*6777b538SAndroid Build Coastguard Worker // run_loop.Run();
44*6777b538SAndroid Build Coastguard Worker // timeout.Cancel();  // Hopefully this is hit before the timeout callback runs.
45*6777b538SAndroid Build Coastguard Worker //
46*6777b538SAndroid Build Coastguard Worker 
47*6777b538SAndroid Build Coastguard Worker #ifndef BASE_CANCELABLE_CALLBACK_H_
48*6777b538SAndroid Build Coastguard Worker #define BASE_CANCELABLE_CALLBACK_H_
49*6777b538SAndroid Build Coastguard Worker 
50*6777b538SAndroid Build Coastguard Worker #include <utility>
51*6777b538SAndroid Build Coastguard Worker 
52*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
53*6777b538SAndroid Build Coastguard Worker #include "base/compiler_specific.h"
54*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
55*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback.h"
56*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback_internal.h"
57*6777b538SAndroid Build Coastguard Worker #include "base/memory/weak_ptr.h"
58*6777b538SAndroid Build Coastguard Worker 
59*6777b538SAndroid Build Coastguard Worker namespace base {
60*6777b538SAndroid Build Coastguard Worker namespace internal {
61*6777b538SAndroid Build Coastguard Worker 
62*6777b538SAndroid Build Coastguard Worker template <typename CallbackType>
63*6777b538SAndroid Build Coastguard Worker class CancelableCallbackImpl {
64*6777b538SAndroid Build Coastguard Worker  public:
65*6777b538SAndroid Build Coastguard Worker   CancelableCallbackImpl() = default;
66*6777b538SAndroid Build Coastguard Worker   CancelableCallbackImpl(const CancelableCallbackImpl&) = delete;
67*6777b538SAndroid Build Coastguard Worker   CancelableCallbackImpl& operator=(const CancelableCallbackImpl&) = delete;
68*6777b538SAndroid Build Coastguard Worker 
69*6777b538SAndroid Build Coastguard Worker   // |callback| must not be null.
CancelableCallbackImpl(CallbackType callback)70*6777b538SAndroid Build Coastguard Worker   explicit CancelableCallbackImpl(CallbackType callback)
71*6777b538SAndroid Build Coastguard Worker       : callback_(std::move(callback)) {
72*6777b538SAndroid Build Coastguard Worker     DCHECK(callback_);
73*6777b538SAndroid Build Coastguard Worker   }
74*6777b538SAndroid Build Coastguard Worker 
75*6777b538SAndroid Build Coastguard Worker   ~CancelableCallbackImpl() = default;
76*6777b538SAndroid Build Coastguard Worker 
77*6777b538SAndroid Build Coastguard Worker   // Cancels and drops the reference to the wrapped callback.
Cancel()78*6777b538SAndroid Build Coastguard Worker   void Cancel() {
79*6777b538SAndroid Build Coastguard Worker     weak_ptr_factory_.InvalidateWeakPtrs();
80*6777b538SAndroid Build Coastguard Worker     callback_.Reset();
81*6777b538SAndroid Build Coastguard Worker   }
82*6777b538SAndroid Build Coastguard Worker 
83*6777b538SAndroid Build Coastguard Worker   // Returns true if the wrapped callback has been cancelled.
IsCancelled()84*6777b538SAndroid Build Coastguard Worker   bool IsCancelled() const {
85*6777b538SAndroid Build Coastguard Worker     return callback_.is_null();
86*6777b538SAndroid Build Coastguard Worker   }
87*6777b538SAndroid Build Coastguard Worker 
88*6777b538SAndroid Build Coastguard Worker   // Sets |callback| as the closure that may be cancelled. |callback| may not
89*6777b538SAndroid Build Coastguard Worker   // be null. Outstanding and any previously wrapped callbacks are cancelled.
Reset(CallbackType callback)90*6777b538SAndroid Build Coastguard Worker   void Reset(CallbackType callback) {
91*6777b538SAndroid Build Coastguard Worker     DCHECK(callback);
92*6777b538SAndroid Build Coastguard Worker     // Outstanding tasks (e.g., posted to a message loop) must not be called.
93*6777b538SAndroid Build Coastguard Worker     Cancel();
94*6777b538SAndroid Build Coastguard Worker     callback_ = std::move(callback);
95*6777b538SAndroid Build Coastguard Worker   }
96*6777b538SAndroid Build Coastguard Worker 
97*6777b538SAndroid Build Coastguard Worker   // Returns a callback that can be disabled by calling Cancel(). This returned
98*6777b538SAndroid Build Coastguard Worker   // callback may only run on the bound SequencedTaskRunner (where
99*6777b538SAndroid Build Coastguard Worker   // CancelableCallback was constructed), but it may be destroyed on any
100*6777b538SAndroid Build Coastguard Worker   // sequence. This means the callback may be handed off to other task runners,
101*6777b538SAndroid Build Coastguard Worker   // e.g. via PostTaskAndReply[WithResult](), to post tasks back on the original
102*6777b538SAndroid Build Coastguard Worker   // bound sequence.
callback()103*6777b538SAndroid Build Coastguard Worker   CallbackType callback() const {
104*6777b538SAndroid Build Coastguard Worker     if (!callback_)
105*6777b538SAndroid Build Coastguard Worker       return CallbackType();
106*6777b538SAndroid Build Coastguard Worker     CallbackType forwarder;
107*6777b538SAndroid Build Coastguard Worker     MakeForwarder(&forwarder);
108*6777b538SAndroid Build Coastguard Worker     return forwarder;
109*6777b538SAndroid Build Coastguard Worker   }
110*6777b538SAndroid Build Coastguard Worker 
111*6777b538SAndroid Build Coastguard Worker  private:
112*6777b538SAndroid Build Coastguard Worker   template <typename... Args>
MakeForwarder(RepeatingCallback<void (Args...)> * out)113*6777b538SAndroid Build Coastguard Worker   void MakeForwarder(RepeatingCallback<void(Args...)>* out) const {
114*6777b538SAndroid Build Coastguard Worker     using ForwarderType = void (CancelableCallbackImpl::*)(Args...);
115*6777b538SAndroid Build Coastguard Worker     ForwarderType forwarder = &CancelableCallbackImpl::ForwardRepeating;
116*6777b538SAndroid Build Coastguard Worker     *out = BindRepeating(forwarder, weak_ptr_factory_.GetWeakPtr());
117*6777b538SAndroid Build Coastguard Worker   }
118*6777b538SAndroid Build Coastguard Worker 
119*6777b538SAndroid Build Coastguard Worker   template <typename... Args>
MakeForwarder(OnceCallback<void (Args...)> * out)120*6777b538SAndroid Build Coastguard Worker   void MakeForwarder(OnceCallback<void(Args...)>* out) const {
121*6777b538SAndroid Build Coastguard Worker     using ForwarderType = void (CancelableCallbackImpl::*)(Args...);
122*6777b538SAndroid Build Coastguard Worker     ForwarderType forwarder = &CancelableCallbackImpl::ForwardOnce;
123*6777b538SAndroid Build Coastguard Worker     *out = BindOnce(forwarder, weak_ptr_factory_.GetWeakPtr());
124*6777b538SAndroid Build Coastguard Worker   }
125*6777b538SAndroid Build Coastguard Worker 
126*6777b538SAndroid Build Coastguard Worker   template <typename... Args>
ForwardRepeating(Args...args)127*6777b538SAndroid Build Coastguard Worker   void ForwardRepeating(Args... args) {
128*6777b538SAndroid Build Coastguard Worker     callback_.Run(std::forward<Args>(args)...);
129*6777b538SAndroid Build Coastguard Worker   }
130*6777b538SAndroid Build Coastguard Worker 
131*6777b538SAndroid Build Coastguard Worker   template <typename... Args>
ForwardOnce(Args...args)132*6777b538SAndroid Build Coastguard Worker   void ForwardOnce(Args... args) {
133*6777b538SAndroid Build Coastguard Worker     weak_ptr_factory_.InvalidateWeakPtrs();
134*6777b538SAndroid Build Coastguard Worker     std::move(callback_).Run(std::forward<Args>(args)...);
135*6777b538SAndroid Build Coastguard Worker   }
136*6777b538SAndroid Build Coastguard Worker 
137*6777b538SAndroid Build Coastguard Worker   // The stored closure that may be cancelled.
138*6777b538SAndroid Build Coastguard Worker   CallbackType callback_;
139*6777b538SAndroid Build Coastguard Worker   mutable base::WeakPtrFactory<CancelableCallbackImpl> weak_ptr_factory_{this};
140*6777b538SAndroid Build Coastguard Worker };
141*6777b538SAndroid Build Coastguard Worker 
142*6777b538SAndroid Build Coastguard Worker }  // namespace internal
143*6777b538SAndroid Build Coastguard Worker 
144*6777b538SAndroid Build Coastguard Worker // Consider using base::WeakPtr directly instead of base::CancelableOnceCallback
145*6777b538SAndroid Build Coastguard Worker // for task cancellation.
146*6777b538SAndroid Build Coastguard Worker template <typename Signature>
147*6777b538SAndroid Build Coastguard Worker using CancelableOnceCallback =
148*6777b538SAndroid Build Coastguard Worker     internal::CancelableCallbackImpl<OnceCallback<Signature>>;
149*6777b538SAndroid Build Coastguard Worker using CancelableOnceClosure = CancelableOnceCallback<void()>;
150*6777b538SAndroid Build Coastguard Worker 
151*6777b538SAndroid Build Coastguard Worker template <typename Signature>
152*6777b538SAndroid Build Coastguard Worker using CancelableRepeatingCallback =
153*6777b538SAndroid Build Coastguard Worker     internal::CancelableCallbackImpl<RepeatingCallback<Signature>>;
154*6777b538SAndroid Build Coastguard Worker using CancelableRepeatingClosure = CancelableRepeatingCallback<void()>;
155*6777b538SAndroid Build Coastguard Worker 
156*6777b538SAndroid Build Coastguard Worker }  // namespace base
157*6777b538SAndroid Build Coastguard Worker 
158*6777b538SAndroid Build Coastguard Worker #endif  // BASE_CANCELABLE_CALLBACK_H_
159