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