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