cancelable_callback.h 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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 butil::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(butil::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. #ifndef BUTIL_CANCELABLE_CALLBACK_H_
  42. #define BUTIL_CANCELABLE_CALLBACK_H_
  43. #include "butil/base_export.h"
  44. #include "butil/bind.h"
  45. #include "butil/callback.h"
  46. #include "butil/callback_internal.h"
  47. #include "butil/compiler_specific.h"
  48. #include "butil/logging.h"
  49. #include "butil/memory/weak_ptr.h"
  50. namespace butil {
  51. template <typename Sig>
  52. class CancelableCallback;
  53. template <>
  54. class CancelableCallback<void(void)> {
  55. public:
  56. CancelableCallback() : weak_factory_(this) {}
  57. // |callback| must not be null.
  58. explicit CancelableCallback(const butil::Callback<void(void)>& callback)
  59. : weak_factory_(this),
  60. callback_(callback) {
  61. DCHECK(!callback.is_null());
  62. InitializeForwarder();
  63. }
  64. ~CancelableCallback() {}
  65. // Cancels and drops the reference to the wrapped callback.
  66. void Cancel() {
  67. weak_factory_.InvalidateWeakPtrs();
  68. forwarder_.Reset();
  69. callback_.Reset();
  70. }
  71. // Returns true if the wrapped callback has been cancelled.
  72. bool IsCancelled() const {
  73. return callback_.is_null();
  74. }
  75. // Sets |callback| as the closure that may be cancelled. |callback| may not
  76. // be null. Outstanding and any previously wrapped callbacks are cancelled.
  77. void Reset(const butil::Callback<void(void)>& callback) {
  78. DCHECK(!callback.is_null());
  79. // Outstanding tasks (e.g., posted to a message loop) must not be called.
  80. Cancel();
  81. // |forwarder_| is no longer valid after Cancel(), so re-bind.
  82. InitializeForwarder();
  83. callback_ = callback;
  84. }
  85. // Returns a callback that can be disabled by calling Cancel().
  86. const butil::Callback<void(void)>& callback() const {
  87. return forwarder_;
  88. }
  89. private:
  90. void Forward() {
  91. callback_.Run();
  92. }
  93. // Helper method to bind |forwarder_| using a weak pointer from
  94. // |weak_factory_|.
  95. void InitializeForwarder() {
  96. forwarder_ = butil::Bind(&CancelableCallback<void(void)>::Forward,
  97. weak_factory_.GetWeakPtr());
  98. }
  99. // Used to ensure Forward() is not run when this object is destroyed.
  100. butil::WeakPtrFactory<CancelableCallback<void(void)> > weak_factory_;
  101. // The wrapper closure.
  102. butil::Callback<void(void)> forwarder_;
  103. // The stored closure that may be cancelled.
  104. butil::Callback<void(void)> callback_;
  105. DISALLOW_COPY_AND_ASSIGN(CancelableCallback);
  106. };
  107. template <typename A1>
  108. class CancelableCallback<void(A1)> {
  109. public:
  110. CancelableCallback() : weak_factory_(this) {}
  111. // |callback| must not be null.
  112. explicit CancelableCallback(const butil::Callback<void(A1)>& callback)
  113. : weak_factory_(this),
  114. callback_(callback) {
  115. DCHECK(!callback.is_null());
  116. InitializeForwarder();
  117. }
  118. ~CancelableCallback() {}
  119. // Cancels and drops the reference to the wrapped callback.
  120. void Cancel() {
  121. weak_factory_.InvalidateWeakPtrs();
  122. forwarder_.Reset();
  123. callback_.Reset();
  124. }
  125. // Returns true if the wrapped callback has been cancelled.
  126. bool IsCancelled() const {
  127. return callback_.is_null();
  128. }
  129. // Sets |callback| as the closure that may be cancelled. |callback| may not
  130. // be null. Outstanding and any previously wrapped callbacks are cancelled.
  131. void Reset(const butil::Callback<void(A1)>& callback) {
  132. DCHECK(!callback.is_null());
  133. // Outstanding tasks (e.g., posted to a message loop) must not be called.
  134. Cancel();
  135. // |forwarder_| is no longer valid after Cancel(), so re-bind.
  136. InitializeForwarder();
  137. callback_ = callback;
  138. }
  139. // Returns a callback that can be disabled by calling Cancel().
  140. const butil::Callback<void(A1)>& callback() const {
  141. return forwarder_;
  142. }
  143. private:
  144. void Forward(A1 a1) const {
  145. callback_.Run(a1);
  146. }
  147. // Helper method to bind |forwarder_| using a weak pointer from
  148. // |weak_factory_|.
  149. void InitializeForwarder() {
  150. forwarder_ = butil::Bind(&CancelableCallback<void(A1)>::Forward,
  151. weak_factory_.GetWeakPtr());
  152. }
  153. // Used to ensure Forward() is not run when this object is destroyed.
  154. butil::WeakPtrFactory<CancelableCallback<void(A1)> > weak_factory_;
  155. // The wrapper closure.
  156. butil::Callback<void(A1)> forwarder_;
  157. // The stored closure that may be cancelled.
  158. butil::Callback<void(A1)> callback_;
  159. DISALLOW_COPY_AND_ASSIGN(CancelableCallback);
  160. };
  161. template <typename A1, typename A2>
  162. class CancelableCallback<void(A1, A2)> {
  163. public:
  164. CancelableCallback() : weak_factory_(this) {}
  165. // |callback| must not be null.
  166. explicit CancelableCallback(const butil::Callback<void(A1, A2)>& callback)
  167. : weak_factory_(this),
  168. callback_(callback) {
  169. DCHECK(!callback.is_null());
  170. InitializeForwarder();
  171. }
  172. ~CancelableCallback() {}
  173. // Cancels and drops the reference to the wrapped callback.
  174. void Cancel() {
  175. weak_factory_.InvalidateWeakPtrs();
  176. forwarder_.Reset();
  177. callback_.Reset();
  178. }
  179. // Returns true if the wrapped callback has been cancelled.
  180. bool IsCancelled() const {
  181. return callback_.is_null();
  182. }
  183. // Sets |callback| as the closure that may be cancelled. |callback| may not
  184. // be null. Outstanding and any previously wrapped callbacks are cancelled.
  185. void Reset(const butil::Callback<void(A1, A2)>& callback) {
  186. DCHECK(!callback.is_null());
  187. // Outstanding tasks (e.g., posted to a message loop) must not be called.
  188. Cancel();
  189. // |forwarder_| is no longer valid after Cancel(), so re-bind.
  190. InitializeForwarder();
  191. callback_ = callback;
  192. }
  193. // Returns a callback that can be disabled by calling Cancel().
  194. const butil::Callback<void(A1, A2)>& callback() const {
  195. return forwarder_;
  196. }
  197. private:
  198. void Forward(A1 a1, A2 a2) const {
  199. callback_.Run(a1, a2);
  200. }
  201. // Helper method to bind |forwarder_| using a weak pointer from
  202. // |weak_factory_|.
  203. void InitializeForwarder() {
  204. forwarder_ = butil::Bind(&CancelableCallback<void(A1, A2)>::Forward,
  205. weak_factory_.GetWeakPtr());
  206. }
  207. // Used to ensure Forward() is not run when this object is destroyed.
  208. butil::WeakPtrFactory<CancelableCallback<void(A1, A2)> > weak_factory_;
  209. // The wrapper closure.
  210. butil::Callback<void(A1, A2)> forwarder_;
  211. // The stored closure that may be cancelled.
  212. butil::Callback<void(A1, A2)> callback_;
  213. DISALLOW_COPY_AND_ASSIGN(CancelableCallback);
  214. };
  215. typedef CancelableCallback<void(void)> CancelableClosure;
  216. } // namespace butil
  217. #endif // BUTIL_CANCELABLE_CALLBACK_H_