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