Chromium Code Reviews| Index: base/cancelable_callback.h |
| diff --git a/base/cancelable_callback.h b/base/cancelable_callback.h |
| index 23dbe6a668c0b30191272e20cb374aa0265e8575..e941efdebe3829b2a72b4169108c65e92f39dafa 100644 |
| --- a/base/cancelable_callback.h |
| +++ b/base/cancelable_callback.h |
| @@ -7,7 +7,12 @@ |
| // wrapped callback until this object is destroyed or Reset()/Cancel() are |
| // called. |
| // |
| -// Thread-safety notes: |
| +// NOTE: |
| +// |
| +// Calling Cancel() brings the object back to its natural, default-constructed |
|
michaeln
2011/11/30 20:04:22
ah... i see
|
| +// state, i.e., callback() will return a null callback. |
|
awong
2011/11/30 20:28:17
callback() -> CancellableCallback::callback()
James Hawkins
2011/11/30 20:31:05
Done.
|
| +// |
| +// THREAD-SAFETY: |
| // |
| // CancelableCallback objects must be created on, posted to, cancelled on, and |
| // destroyed on the same thread. |
| @@ -25,7 +30,7 @@ |
| // MessageLoop::current()->Quit(); |
| // } |
| // |
| -// CancelableCallback timeout(base::Bind(&TimeoutCallback, "Test timed out.")); |
| +// CancelableClosure timeout(base::Bind(&TimeoutCallback, "Test timed out.")); |
| // MessageLoop::current()->PostDelayedTask(FROM_HERE, timeout.callback(), |
| // 4000) // 4 seconds to run. |
| // RunIntensiveTest(); |
| @@ -37,53 +42,162 @@ |
| #define BASE_CANCELABLE_CALLBACK_H_ |
| #pragma once |
| -#include "base/callback.h" |
| #include "base/base_export.h" |
| +#include "base/bind.h" |
| +#include "base/callback.h" |
| +#include "base/callback_internal.h" |
| +#include "base/compiler_specific.h" |
| +#include "base/logging.h" |
| #include "base/memory/weak_ptr.h" |
| namespace base { |
| -class BASE_EXPORT CancelableCallback { |
| +template <typename Sig> |
| +class CancelableCallback; |
| + |
| +template <> |
| +class CancelableCallback<void(void)> { |
| public: |
| - CancelableCallback(); |
| + CancelableCallback() : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {} |
| // |callback| must not be null. |
| - explicit CancelableCallback(const base::Closure& callback); |
| + explicit CancelableCallback(const base::Callback<void(void)>& callback) |
| + : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
| + callback_(callback) { |
| + DCHECK(!callback.is_null()); |
| + InitializeForwarder(); |
| + } |
| - ~CancelableCallback(); |
| + ~CancelableCallback() {} |
| // Cancels and drops the reference to the wrapped callback. |
| - void Cancel(); |
| + void Cancel() { |
| + weak_factory_.InvalidateWeakPtrs(); |
| + forwarder_.Reset(); |
| + callback_.Reset(); |
| + } |
| // Returns true if the wrapped callback has been cancelled. |
| - bool IsCancelled() const; |
| + bool IsCancelled() const { |
| + return callback_.is_null(); |
| + } |
| // Sets |callback| as the closure that may be cancelled. |callback| may not |
| // be null. Outstanding and any previously wrapped callbacks are cancelled. |
| - void Reset(const base::Closure& callback); |
| + void Reset(const base::Callback<void(void)>& callback) { |
| + DCHECK(!callback.is_null()); |
| + |
| + // Outstanding tasks (e.g., posted to a message loop) must not be called. |
| + Cancel(); |
| + |
| + // |forwarder_| is no longer valid after Cancel(), so re-bind. |
| + InitializeForwarder(); |
| + |
| + callback_ = callback; |
| + } |
| // Returns a callback that can be disabled by calling Cancel(). |
| - const base::Closure& callback() const; |
| + const base::Callback<void(void)>& callback() const { |
| + return forwarder_; |
| + } |
| private: |
| - void RunCallback(); |
| + void Forward() { |
| + callback_.Run(); |
| + } |
| // Helper method to bind |forwarder_| using a weak pointer from |
| // |weak_factory_|. |
| - void InitializeForwarder(); |
| + void InitializeForwarder() { |
| + forwarder_ = base::Bind(&CancelableCallback<void(void)>::Forward, |
| + weak_factory_.GetWeakPtr()); |
| + } |
| - // Used to ensure RunCallback() is not run when this object is destroyed. |
| - base::WeakPtrFactory<CancelableCallback> weak_factory_; |
| + // Used to ensure Forward() is not run when this object is destroyed. |
| + base::WeakPtrFactory<CancelableCallback<void(void)> > weak_factory_; |
| // The wrapper closure. |
| - base::Closure forwarder_; |
| + base::Callback<void(void)> forwarder_; |
| // The stored closure that may be cancelled. |
| - base::Closure callback_; |
| + base::Callback<void(void)> callback_; |
| DISALLOW_COPY_AND_ASSIGN(CancelableCallback); |
| }; |
| +template <typename A1> |
| +class CancelableCallback<void(A1)> { |
| + public: |
| + CancelableCallback() : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {} |
| + |
| + // |callback| must not be null. |
| + explicit CancelableCallback(const base::Callback<void(A1)>& callback) |
| + : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
| + callback_(callback) { |
| + DCHECK(!callback.is_null()); |
| + InitializeForwarder(); |
| + } |
| + |
| + ~CancelableCallback() {} |
| + |
| + // Cancels and drops the reference to the wrapped callback. |
| + void Cancel() { |
| + weak_factory_.InvalidateWeakPtrs(); |
| + forwarder_.Reset(); |
| + callback_.Reset(); |
| + } |
| + |
| + // Returns true if the wrapped callback has been cancelled. |
| + bool IsCancelled() const { |
| + return callback_.is_null(); |
| + } |
| + |
| + // Sets |callback| as the closure that may be cancelled. |callback| may not |
| + // be null. Outstanding and any previously wrapped callbacks are cancelled. |
| + void Reset(const base::Callback<void(A1)>& callback) { |
| + DCHECK(!callback.is_null()); |
| + |
| + // Outstanding tasks (e.g., posted to a message loop) must not be called. |
| + Cancel(); |
| + |
| + // |forwarder_| is no longer valid after Cancel(), so re-bind. |
| + InitializeForwarder(); |
| + |
| + callback_ = callback; |
| + } |
| + |
| + // Returns a callback that can be disabled by calling Cancel(). |
| + const base::Callback<void(A1)>& callback() const { |
| + return forwarder_; |
| + } |
| + |
| + private: |
| + void Forward( |
| + typename internal::CallbackParamTraits<A1>::ForwardType a1) const { |
| + callback_.Run(a1); |
| + } |
| + |
| + // Helper method to bind |forwarder_| using a weak pointer from |
| + // |weak_factory_|. |
| + void InitializeForwarder() { |
| + forwarder_ = base::Bind(&CancelableCallback<void(A1)>::Forward, |
| + weak_factory_.GetWeakPtr()); |
| + } |
| + |
| + // Used to ensure Forward() is not run when this object is destroyed. |
| + base::WeakPtrFactory<CancelableCallback<void(A1)> > weak_factory_; |
| + |
| + // The wrapper closure. |
| + base::Callback<void(A1)> forwarder_; |
| + |
| + // The stored closure that may be cancelled. |
| + base::Callback<void(A1)> callback_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(CancelableCallback); |
| +}; |
| + |
| +typedef CancelableCallback<void(void)> CancelableClosure; |
| + |
| } // namespace base |
| #endif // BASE_CANCELABLE_CALLBACK_H_ |