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