blob: 4de7d12201d184d64fb2bda9d1aa5de62b466d7f [file] [log] [blame]
[email protected]b77576f52011-11-24 04:12:041// 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//
[email protected]d4d57df2011-11-30 20:33:5210// NOTE:
11//
12// Calling CancellableCallback::Cancel() brings the object back to its natural,
13// default-constructed state, i.e., CancellableCallback::callback() will return
14// a null callback.
15//
16// THREAD-SAFETY:
[email protected]b77576f52011-11-24 04:12:0417//
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()->Quit();
32// }
33//
[email protected]d4d57df2011-11-30 20:33:5234// CancelableClosure timeout(base::Bind(&TimeoutCallback, "Test timed out."));
[email protected]b77576f52011-11-24 04:12:0435// 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#pragma once
45
[email protected]b77576f52011-11-24 04:12:0446#include "base/base_export.h"
[email protected]d4d57df2011-11-30 20:33:5247#include "base/bind.h"
48#include "base/callback.h"
49#include "base/callback_internal.h"
50#include "base/compiler_specific.h"
51#include "base/logging.h"
[email protected]b77576f52011-11-24 04:12:0452#include "base/memory/weak_ptr.h"
53
54namespace base {
55
[email protected]d4d57df2011-11-30 20:33:5256template <typename Sig>
57class CancelableCallback;
58
59template <>
60class CancelableCallback<void(void)> {
[email protected]b77576f52011-11-24 04:12:0461 public:
[email protected]d4d57df2011-11-30 20:33:5262 CancelableCallback() : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {}
[email protected]b77576f52011-11-24 04:12:0463
64 // |callback| must not be null.
[email protected]d4d57df2011-11-30 20:33:5265 explicit CancelableCallback(const base::Callback<void(void)>& callback)
66 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
67 callback_(callback) {
68 DCHECK(!callback.is_null());
69 InitializeForwarder();
70 }
[email protected]b77576f52011-11-24 04:12:0471
[email protected]d4d57df2011-11-30 20:33:5272 ~CancelableCallback() {}
[email protected]b77576f52011-11-24 04:12:0473
74 // Cancels and drops the reference to the wrapped callback.
[email protected]d4d57df2011-11-30 20:33:5275 void Cancel() {
76 weak_factory_.InvalidateWeakPtrs();
77 forwarder_.Reset();
78 callback_.Reset();
79 }
[email protected]b77576f52011-11-24 04:12:0480
81 // Returns true if the wrapped callback has been cancelled.
[email protected]d4d57df2011-11-30 20:33:5282 bool IsCancelled() const {
83 return callback_.is_null();
84 }
[email protected]b77576f52011-11-24 04:12:0485
86 // Sets |callback| as the closure that may be cancelled. |callback| may not
87 // be null. Outstanding and any previously wrapped callbacks are cancelled.
[email protected]d4d57df2011-11-30 20:33:5288 void Reset(const base::Callback<void(void)>& callback) {
89 DCHECK(!callback.is_null());
90
91 // Outstanding tasks (e.g., posted to a message loop) must not be called.
92 Cancel();
93
94 // |forwarder_| is no longer valid after Cancel(), so re-bind.
95 InitializeForwarder();
96
97 callback_ = callback;
98 }
[email protected]b77576f52011-11-24 04:12:0499
100 // Returns a callback that can be disabled by calling Cancel().
[email protected]d4d57df2011-11-30 20:33:52101 const base::Callback<void(void)>& callback() const {
102 return forwarder_;
103 }
[email protected]b77576f52011-11-24 04:12:04104
105 private:
[email protected]d4d57df2011-11-30 20:33:52106 void Forward() {
107 callback_.Run();
108 }
[email protected]b77576f52011-11-24 04:12:04109
110 // Helper method to bind |forwarder_| using a weak pointer from
111 // |weak_factory_|.
[email protected]d4d57df2011-11-30 20:33:52112 void InitializeForwarder() {
113 forwarder_ = base::Bind(&CancelableCallback<void(void)>::Forward,
114 weak_factory_.GetWeakPtr());
115 }
[email protected]b77576f52011-11-24 04:12:04116
[email protected]d4d57df2011-11-30 20:33:52117 // Used to ensure Forward() is not run when this object is destroyed.
118 base::WeakPtrFactory<CancelableCallback<void(void)> > weak_factory_;
[email protected]b77576f52011-11-24 04:12:04119
120 // The wrapper closure.
[email protected]d4d57df2011-11-30 20:33:52121 base::Callback<void(void)> forwarder_;
[email protected]b77576f52011-11-24 04:12:04122
123 // The stored closure that may be cancelled.
[email protected]d4d57df2011-11-30 20:33:52124 base::Callback<void(void)> callback_;
[email protected]b77576f52011-11-24 04:12:04125
126 DISALLOW_COPY_AND_ASSIGN(CancelableCallback);
127};
128
[email protected]d4d57df2011-11-30 20:33:52129template <typename A1>
130class CancelableCallback<void(A1)> {
131 public:
132 CancelableCallback() : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {}
133
134 // |callback| must not be null.
135 explicit CancelableCallback(const base::Callback<void(A1)>& callback)
136 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
137 callback_(callback) {
138 DCHECK(!callback.is_null());
139 InitializeForwarder();
140 }
141
142 ~CancelableCallback() {}
143
144 // Cancels and drops the reference to the wrapped callback.
145 void Cancel() {
146 weak_factory_.InvalidateWeakPtrs();
147 forwarder_.Reset();
148 callback_.Reset();
149 }
150
151 // Returns true if the wrapped callback has been cancelled.
152 bool IsCancelled() const {
153 return callback_.is_null();
154 }
155
156 // Sets |callback| as the closure that may be cancelled. |callback| may not
157 // be null. Outstanding and any previously wrapped callbacks are cancelled.
158 void Reset(const base::Callback<void(A1)>& callback) {
159 DCHECK(!callback.is_null());
160
161 // Outstanding tasks (e.g., posted to a message loop) must not be called.
162 Cancel();
163
164 // |forwarder_| is no longer valid after Cancel(), so re-bind.
165 InitializeForwarder();
166
167 callback_ = callback;
168 }
169
170 // Returns a callback that can be disabled by calling Cancel().
171 const base::Callback<void(A1)>& callback() const {
172 return forwarder_;
173 }
174
175 private:
[email protected]e24f8762011-12-20 00:10:04176 void Forward(A1 a1) const {
[email protected]d4d57df2011-11-30 20:33:52177 callback_.Run(a1);
178 }
179
180 // Helper method to bind |forwarder_| using a weak pointer from
181 // |weak_factory_|.
182 void InitializeForwarder() {
183 forwarder_ = base::Bind(&CancelableCallback<void(A1)>::Forward,
184 weak_factory_.GetWeakPtr());
185 }
186
187 // Used to ensure Forward() is not run when this object is destroyed.
188 base::WeakPtrFactory<CancelableCallback<void(A1)> > weak_factory_;
189
190 // The wrapper closure.
191 base::Callback<void(A1)> forwarder_;
192
193 // The stored closure that may be cancelled.
194 base::Callback<void(A1)> callback_;
195
196 DISALLOW_COPY_AND_ASSIGN(CancelableCallback);
197};
198
199typedef CancelableCallback<void(void)> CancelableClosure;
200
[email protected]b77576f52011-11-24 04:12:04201} // namespace base
202
203#endif // BASE_CANCELABLE_CALLBACK_H_