diff options
author | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-30 20:33:52 +0000 |
---|---|---|
committer | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-30 20:33:52 +0000 |
commit | d4d57df406ef7e02e69d8de18efc8bdb917ac4ba (patch) | |
tree | 8b677e46226f3b8cd077c8b06d9bcf7d4f691e0e /base | |
parent | 43cb919add660ef0c3ea1c3b49ac9a2e2a1d2f7d (diff) | |
download | chromium_src-d4d57df406ef7e02e69d8de18efc8bdb917ac4ba.zip chromium_src-d4d57df406ef7e02e69d8de18efc8bdb917ac4ba.tar.gz chromium_src-d4d57df406ef7e02e69d8de18efc8bdb917ac4ba.tar.bz2 |
base::Bind: Implement a 1-arity CancelableCallback and use this to implement
net::CancelableCompletionClosure.
BUG=none
TEST=none
R=ajwong@chromium.org
Review URL: http://codereview.chromium.org/8662047
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@112279 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/base.gypi | 1 | ||||
-rw-r--r-- | base/cancelable_callback.cc | 60 | ||||
-rw-r--r-- | base/cancelable_callback.h | 149 | ||||
-rw-r--r-- | base/cancelable_callback_unittest.cc | 27 |
4 files changed, 147 insertions, 90 deletions
diff --git a/base/base.gypi b/base/base.gypi index f2b1b6a..52fef77 100644 --- a/base/base.gypi +++ b/base/base.gypi @@ -61,7 +61,6 @@ 'callback_internal.cc', 'callback_internal.h', 'callback_old.h', - 'cancelable_callback.cc', 'cancelable_callback.h', 'command_line.cc', 'command_line.h', diff --git a/base/cancelable_callback.cc b/base/cancelable_callback.cc deleted file mode 100644 index da9777d..0000000 --- a/base/cancelable_callback.cc +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/cancelable_callback.h" - -#include "base/bind.h" -#include "base/compiler_specific.h" -#include "base/logging.h" - -namespace base { - -CancelableCallback::CancelableCallback() - : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { -} - -CancelableCallback::CancelableCallback(const base::Closure& callback) - : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), - callback_(callback) { - DCHECK(!callback.is_null()); - InitializeForwarder(); -} - -CancelableCallback::~CancelableCallback() {} - -void CancelableCallback::Cancel() { - weak_factory_.InvalidateWeakPtrs(); - callback_.Reset(); -} - -bool CancelableCallback::IsCancelled() const { - return callback_.is_null(); -} - -void CancelableCallback::Reset(const base::Closure& 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; -} - -const base::Closure& CancelableCallback::callback() const { - return forwarder_; -} - -void CancelableCallback::RunCallback() { - callback_.Run(); -} - -void CancelableCallback::InitializeForwarder() { - forwarder_ = base::Bind(&CancelableCallback::RunCallback, - weak_factory_.GetWeakPtr()); -} - -} // namespace bind diff --git a/base/cancelable_callback.h b/base/cancelable_callback.h index 23dbe6a..b432f61 100644 --- a/base/cancelable_callback.h +++ b/base/cancelable_callback.h @@ -7,7 +7,13 @@ // wrapped callback until this object is destroyed or Reset()/Cancel() are // called. // -// Thread-safety notes: +// NOTE: +// +// Calling CancellableCallback::Cancel() brings the object back to its natural, +// default-constructed state, i.e., CancellableCallback::callback() will return +// a null callback. +// +// THREAD-SAFETY: // // CancelableCallback objects must be created on, posted to, cancelled on, and // destroyed on the same thread. @@ -25,7 +31,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 +43,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_ diff --git a/base/cancelable_callback_unittest.cc b/base/cancelable_callback_unittest.cc index 980359b..51a2a09 100644 --- a/base/cancelable_callback_unittest.cc +++ b/base/cancelable_callback_unittest.cc @@ -28,7 +28,7 @@ void RefCountedParam(const scoped_refptr<TestRefCounted>& ref_counted) {} // - After Cancel(), Run() completes but has no effect. TEST(CancelableCallbackTest, Cancel) { int count = 0; - CancelableCallback cancelable( + CancelableClosure cancelable( base::Bind(&Increment, base::Unretained(&count))); base::Closure callback = cancelable.callback(); @@ -45,26 +45,29 @@ TEST(CancelableCallbackTest, Cancel) { // Cancel() called multiple times. // - Cancel() cancels all copies of the wrapped callback. +// - Calling Cancel() more than once has no effect. +// - After Cancel(), callback() returns a null callback. TEST(CancelableCallbackTest, MultipleCancel) { int count = 0; - CancelableCallback cancelable( + CancelableClosure cancelable( base::Bind(&Increment, base::Unretained(&count))); base::Closure callback1 = cancelable.callback(); + base::Closure callback2 = cancelable.callback(); cancelable.Cancel(); callback1.Run(); EXPECT_EQ(0, count); - base::Closure callback2 = cancelable.callback(); callback2.Run(); EXPECT_EQ(0, count); - // Cancel() should have no effect, but callback() is still runnable. - base::Closure callback3 = cancelable.callback(); + // Calling Cancel() again has no effect. cancelable.Cancel(); - callback3.Run(); - EXPECT_EQ(0, count); + + // callback() of a cancelled callback is null. + base::Closure callback3 = cancelable.callback(); + EXPECT_TRUE(callback3.is_null()); } // CancelableCallback destroyed before callback is run. @@ -74,7 +77,7 @@ TEST(CancelableCallbackTest, CallbackCanceledOnDestruction) { base::Closure callback; { - CancelableCallback cancelable( + CancelableClosure cancelable( base::Bind(&Increment, base::Unretained(&count))); callback = cancelable.callback(); @@ -92,7 +95,7 @@ TEST(CancelableCallbackTest, CancelDropsCallback) { scoped_refptr<TestRefCounted> ref_counted = new TestRefCounted; EXPECT_TRUE(ref_counted->HasOneRef()); - CancelableCallback cancelable(base::Bind(RefCountedParam, ref_counted)); + CancelableClosure cancelable(base::Bind(RefCountedParam, ref_counted)); EXPECT_FALSE(cancelable.IsCancelled()); EXPECT_TRUE(ref_counted.get()); EXPECT_FALSE(ref_counted->HasOneRef()); @@ -109,7 +112,7 @@ TEST(CancelableCallbackTest, CancelDropsCallback) { // - Reset() deactivates outstanding callbacks. TEST(CancelableCallbackTest, Reset) { int count = 0; - CancelableCallback cancelable( + CancelableClosure cancelable( base::Bind(&Increment, base::Unretained(&count))); base::Closure callback = cancelable.callback(); @@ -140,7 +143,7 @@ TEST(CancelableCallbackTest, Reset) { // IsCanceled(). // - Cancel() transforms the CancelableCallback into a cancelled state. TEST(CancelableCallbackTest, IsNull) { - CancelableCallback cancelable; + CancelableClosure cancelable; EXPECT_TRUE(cancelable.IsCancelled()); int count = 0; @@ -158,7 +161,7 @@ TEST(CancelableCallbackTest, PostTask) { MessageLoop loop(MessageLoop::TYPE_DEFAULT); int count = 0; - CancelableCallback cancelable(base::Bind(&Increment, + CancelableClosure cancelable(base::Bind(&Increment, base::Unretained(&count))); MessageLoop::current()->PostTask(FROM_HERE, cancelable.callback()); |