1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4//
5// CancelableCallback is a wrapper around base::Callback that allows
6// cancellation of a callback. CancelableCallback takes a reference on the
7// wrapped callback until this object is destroyed or Reset()/Cancel() are
8// called.
9//
10// NOTE:
11//
12// Calling CancelableCallback::Cancel() brings the object back to its natural,
13// default-constructed state, i.e., CancelableCallback::callback() will return
14// a null callback.
15//
16// THREAD-SAFETY:
17//
18// CancelableCallback objects must be created on, posted to, cancelled on, and
19// destroyed on the same thread.
20//
21//
22// EXAMPLE USAGE:
23//
24// In the following example, the test is verifying that RunIntensiveTest()
25// Quit()s the message loop within 4 seconds. The cancelable callback is posted
26// to the message loop, the intensive test runs, the message loop is run,
27// then the callback is cancelled.
28//
29// void TimeoutCallback(const std::string& timeout_message) {
30//   FAIL() << timeout_message;
31//   MessageLoop::current()->QuitWhenIdle();
32// }
33//
34// CancelableClosure timeout(base::Bind(&TimeoutCallback, "Test timed out."));
35// MessageLoop::current()->PostDelayedTask(FROM_HERE, timeout.callback(),
36//                                         4000)  // 4 seconds to run.
37// RunIntensiveTest();
38// MessageLoop::current()->Run();
39// timeout.Cancel();  // Hopefully this is hit before the timeout callback runs.
40//
41
42#ifndef BASE_CANCELABLE_CALLBACK_H_
43#define BASE_CANCELABLE_CALLBACK_H_
44
45#include "base/base_export.h"
46#include "base/bind.h"
47#include "base/callback.h"
48#include "base/callback_internal.h"
49#include "base/compiler_specific.h"
50#include "base/logging.h"
51#include "base/memory/weak_ptr.h"
52
53namespace base {
54
55template <typename Sig>
56class CancelableCallback;
57
58template <>
59class CancelableCallback<void(void)> {
60 public:
61  CancelableCallback() : weak_factory_(this) {}
62
63  // |callback| must not be null.
64  explicit CancelableCallback(const base::Callback<void(void)>& callback)
65      : weak_factory_(this),
66        callback_(callback) {
67    DCHECK(!callback.is_null());
68    InitializeForwarder();
69  }
70
71  ~CancelableCallback() {}
72
73  // Cancels and drops the reference to the wrapped callback.
74  void Cancel() {
75    weak_factory_.InvalidateWeakPtrs();
76    forwarder_.Reset();
77    callback_.Reset();
78  }
79
80  // Returns true if the wrapped callback has been cancelled.
81  bool IsCancelled() const {
82    return callback_.is_null();
83  }
84
85  // Sets |callback| as the closure that may be cancelled. |callback| may not
86  // be null. Outstanding and any previously wrapped callbacks are cancelled.
87  void Reset(const base::Callback<void(void)>& callback) {
88    DCHECK(!callback.is_null());
89
90    // Outstanding tasks (e.g., posted to a message loop) must not be called.
91    Cancel();
92
93    // |forwarder_| is no longer valid after Cancel(), so re-bind.
94    InitializeForwarder();
95
96    callback_ = callback;
97  }
98
99  // Returns a callback that can be disabled by calling Cancel().
100  const base::Callback<void(void)>& callback() const {
101    return forwarder_;
102  }
103
104 private:
105  void Forward() {
106    callback_.Run();
107  }
108
109  // Helper method to bind |forwarder_| using a weak pointer from
110  // |weak_factory_|.
111  void InitializeForwarder() {
112    forwarder_ = base::Bind(&CancelableCallback<void(void)>::Forward,
113                            weak_factory_.GetWeakPtr());
114  }
115
116  // Used to ensure Forward() is not run when this object is destroyed.
117  base::WeakPtrFactory<CancelableCallback<void(void)> > weak_factory_;
118
119  // The wrapper closure.
120  base::Callback<void(void)> forwarder_;
121
122  // The stored closure that may be cancelled.
123  base::Callback<void(void)> callback_;
124
125  DISALLOW_COPY_AND_ASSIGN(CancelableCallback);
126};
127
128template <typename A1>
129class CancelableCallback<void(A1)> {
130 public:
131  CancelableCallback() : weak_factory_(this) {}
132
133  // |callback| must not be null.
134  explicit CancelableCallback(const base::Callback<void(A1)>& callback)
135      : weak_factory_(this),
136        callback_(callback) {
137    DCHECK(!callback.is_null());
138    InitializeForwarder();
139  }
140
141  ~CancelableCallback() {}
142
143  // Cancels and drops the reference to the wrapped callback.
144  void Cancel() {
145    weak_factory_.InvalidateWeakPtrs();
146    forwarder_.Reset();
147    callback_.Reset();
148  }
149
150  // Returns true if the wrapped callback has been cancelled.
151  bool IsCancelled() const {
152    return callback_.is_null();
153  }
154
155  // Sets |callback| as the closure that may be cancelled. |callback| may not
156  // be null. Outstanding and any previously wrapped callbacks are cancelled.
157  void Reset(const base::Callback<void(A1)>& callback) {
158    DCHECK(!callback.is_null());
159
160    // Outstanding tasks (e.g., posted to a message loop) must not be called.
161    Cancel();
162
163    // |forwarder_| is no longer valid after Cancel(), so re-bind.
164    InitializeForwarder();
165
166    callback_ = callback;
167  }
168
169  // Returns a callback that can be disabled by calling Cancel().
170  const base::Callback<void(A1)>& callback() const {
171    return forwarder_;
172  }
173
174 private:
175  void Forward(A1 a1) const {
176    callback_.Run(a1);
177  }
178
179  // Helper method to bind |forwarder_| using a weak pointer from
180  // |weak_factory_|.
181  void InitializeForwarder() {
182    forwarder_ = base::Bind(&CancelableCallback<void(A1)>::Forward,
183                            weak_factory_.GetWeakPtr());
184  }
185
186  // Used to ensure Forward() is not run when this object is destroyed.
187  base::WeakPtrFactory<CancelableCallback<void(A1)> > weak_factory_;
188
189  // The wrapper closure.
190  base::Callback<void(A1)> forwarder_;
191
192  // The stored closure that may be cancelled.
193  base::Callback<void(A1)> callback_;
194
195  DISALLOW_COPY_AND_ASSIGN(CancelableCallback);
196};
197
198template <typename A1, typename A2>
199class CancelableCallback<void(A1, A2)> {
200 public:
201  CancelableCallback() : weak_factory_(this) {}
202
203  // |callback| must not be null.
204  explicit CancelableCallback(const base::Callback<void(A1, A2)>& callback)
205      : weak_factory_(this),
206        callback_(callback) {
207    DCHECK(!callback.is_null());
208    InitializeForwarder();
209  }
210
211  ~CancelableCallback() {}
212
213  // Cancels and drops the reference to the wrapped callback.
214  void Cancel() {
215    weak_factory_.InvalidateWeakPtrs();
216    forwarder_.Reset();
217    callback_.Reset();
218  }
219
220  // Returns true if the wrapped callback has been cancelled.
221  bool IsCancelled() const {
222    return callback_.is_null();
223  }
224
225  // Sets |callback| as the closure that may be cancelled. |callback| may not
226  // be null. Outstanding and any previously wrapped callbacks are cancelled.
227  void Reset(const base::Callback<void(A1, A2)>& callback) {
228    DCHECK(!callback.is_null());
229
230    // Outstanding tasks (e.g., posted to a message loop) must not be called.
231    Cancel();
232
233    // |forwarder_| is no longer valid after Cancel(), so re-bind.
234    InitializeForwarder();
235
236    callback_ = callback;
237  }
238
239  // Returns a callback that can be disabled by calling Cancel().
240  const base::Callback<void(A1, A2)>& callback() const {
241    return forwarder_;
242  }
243
244 private:
245  void Forward(A1 a1, A2 a2) const {
246    callback_.Run(a1, a2);
247  }
248
249  // Helper method to bind |forwarder_| using a weak pointer from
250  // |weak_factory_|.
251  void InitializeForwarder() {
252    forwarder_ = base::Bind(&CancelableCallback<void(A1, A2)>::Forward,
253                            weak_factory_.GetWeakPtr());
254  }
255
256  // Used to ensure Forward() is not run when this object is destroyed.
257  base::WeakPtrFactory<CancelableCallback<void(A1, A2)> > weak_factory_;
258
259  // The wrapper closure.
260  base::Callback<void(A1, A2)> forwarder_;
261
262  // The stored closure that may be cancelled.
263  base::Callback<void(A1, A2)> callback_;
264
265  DISALLOW_COPY_AND_ASSIGN(CancelableCallback);
266};
267
268typedef CancelableCallback<void(void)> CancelableClosure;
269
270}  // namespace base
271
272#endif  // BASE_CANCELABLE_CALLBACK_H_
273