From 935405891d4f2cb40c4fe287e3e4c06ade5c38ce Mon Sep 17 00:00:00 2001 From: "ajwong@chromium.org" Date: Mon, 16 May 2011 22:35:14 +0000 Subject: Support binding WeakPtr<> to methods with void return types. This should give functionality similar to ScopedRunnableMethodFactory. Note that binding a WeakPtr only make sense with methods with void return types. If the return type is not void, then it is unclear what the function should return when the pointer is invalidated. This code adds a compile time assert to check the return type. BUG=35223 TEST=unittests Review URL: http://codereview.chromium.org/7015064 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@85549 0039d316-1c4b-4281-b951-d872f2087c98 --- base/bind_helpers.h | 9 +- base/bind_internal.h | 569 +++++++++++++++++++++++++++++++++++++----- base/bind_internal.h.pump | 63 ++++- base/bind_internal_win.h | 40 +++ base/bind_internal_win.h.pump | 4 + base/bind_unittest.cc | 52 +++- base/callback.h | 2 +- base/callback.h.pump | 8 +- base/template_util.h | 5 +- 9 files changed, 676 insertions(+), 76 deletions(-) diff --git a/base/bind_helpers.h b/base/bind_helpers.h index 73fd81e..e4b4a17 100644 --- a/base/bind_helpers.h +++ b/base/bind_helpers.h @@ -52,6 +52,7 @@ #pragma once #include "base/basictypes.h" +#include "base/memory/weak_ptr.h" #include "base/template_util.h" namespace base { @@ -215,7 +216,7 @@ const T& Unwrap(ConstRefWrapper const_ref) { // Utility for handling different refcounting semantics in the Bind() // function. -template +template struct MaybeRefcount; template @@ -248,6 +249,12 @@ struct MaybeRefcount { static void Release(const T* o) { o->Release(); } }; +template +struct MaybeRefcount > { + static void AddRef(const WeakPtr&) {} + static void Release(const WeakPtr&) {} +}; + } // namespace internal template diff --git a/base/bind_internal.h b/base/bind_internal.h index 606e2b0..203a286 100644 --- a/base/bind_internal.h +++ b/base/bind_internal.h @@ -14,6 +14,7 @@ #include "base/bind_helpers.h" #include "base/callback_internal.h" +#include "base/memory/weak_ptr.h" #include "base/template_util.h" #include "build/build_config.h" @@ -39,10 +40,21 @@ namespace internal { // a calback. // InvokerStorageN<> -- Provides storage for the bound parameters, and // typedefs to the above. +// IsWeakMethod<> -- Determines if we are binding a method to a WeakPtr<>. // // More details about the design of each class is included in a comment closer // to their defition. + +// IsWeakMethod determines if we are binding a method to a WeakPtr<> for an +// object. It is used to select an InvokerN that will no-op itself in the +// event the WeakPtr<> for the target object is invalidated. +template +struct IsWeakMethod : public false_type {}; + +template +struct IsWeakMethod > : public true_type {}; + // FunctionTraits<> // // The FunctionTraits<> template determines the type of function, and also @@ -75,6 +87,8 @@ struct FunctionTraits { typedef R (*NormalizedSig)(); typedef false_type IsMethod; + typedef R Return; + }; // Method: Arity 0. @@ -83,6 +97,8 @@ struct FunctionTraits { typedef R (T::*NormalizedSig)(); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; @@ -94,6 +110,8 @@ struct FunctionTraits { typedef R (T::*NormalizedSig)(); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; @@ -104,6 +122,9 @@ template struct FunctionTraits { typedef R (*NormalizedSig)(X1); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; @@ -115,6 +136,8 @@ struct FunctionTraits { typedef R (T::*NormalizedSig)(X1); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -127,6 +150,8 @@ struct FunctionTraits { typedef R (T::*NormalizedSig)(X1); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -138,6 +163,9 @@ template struct FunctionTraits { typedef R (*NormalizedSig)(X1, X2); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -150,6 +178,8 @@ struct FunctionTraits { typedef R (T::*NormalizedSig)(X1, X2); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -163,6 +193,8 @@ struct FunctionTraits { typedef R (T::*NormalizedSig)(X1, X2); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -175,6 +207,9 @@ template struct FunctionTraits { typedef R (*NormalizedSig)(X1, X2, X3); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -188,6 +223,8 @@ struct FunctionTraits { typedef R (T::*NormalizedSig)(X1, X2, X3); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -202,6 +239,8 @@ struct FunctionTraits { typedef R (T::*NormalizedSig)(X1, X2, X3); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -215,6 +254,9 @@ template struct FunctionTraits { typedef R (*NormalizedSig)(X1, X2, X3, X4); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -230,6 +272,8 @@ struct FunctionTraits { typedef R (T::*NormalizedSig)(X1, X2, X3, X4); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -246,6 +290,8 @@ struct FunctionTraits { typedef R (T::*NormalizedSig)(X1, X2, X3, X4); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -261,6 +307,9 @@ template { typedef R (*NormalizedSig)(X1, X2, X3, X4, X5); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -277,6 +326,8 @@ struct FunctionTraits { typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -294,6 +345,8 @@ struct FunctionTraits { typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -310,6 +363,9 @@ template { typedef R (*NormalizedSig)(X1, X2, X3, X4, X5, X6); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -327,6 +383,8 @@ struct FunctionTraits { typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5, X6); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -345,6 +403,8 @@ struct FunctionTraits { typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5, X6); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; typedef X1 B2; @@ -376,12 +436,12 @@ struct FunctionTraits { // templates classes in the system to only have as many specializations as // the max arity of function we wish to support. -template +template struct Invoker0; // Function: Arity 0 -> 0. template -struct Invoker0 { +struct Invoker0 { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast(base); return invoker->f_(); @@ -390,7 +450,7 @@ struct Invoker0 { // Function: Arity 1 -> 1. template -struct Invoker0 { +struct Invoker0 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x1) { StorageType* invoker = static_cast(base); @@ -400,7 +460,7 @@ struct Invoker0 { // Function: Arity 2 -> 2. template -struct Invoker0 { +struct Invoker0 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x1, typename internal::ParamTraits::ForwardType x2) { @@ -412,7 +472,7 @@ struct Invoker0 { // Function: Arity 3 -> 3. template -struct Invoker0 { +struct Invoker0 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x1, typename internal::ParamTraits::ForwardType x2, @@ -425,7 +485,7 @@ struct Invoker0 { // Function: Arity 4 -> 4. template -struct Invoker0 { +struct Invoker0 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x1, typename internal::ParamTraits::ForwardType x2, @@ -439,7 +499,7 @@ struct Invoker0 { // Function: Arity 5 -> 5. template -struct Invoker0 { +struct Invoker0 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x1, typename internal::ParamTraits::ForwardType x2, @@ -454,7 +514,7 @@ struct Invoker0 { // Function: Arity 6 -> 6. template -struct Invoker0 { +struct Invoker0 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x1, typename internal::ParamTraits::ForwardType x2, @@ -467,12 +527,12 @@ struct Invoker0 { } }; -template +template struct Invoker1; // Function: Arity 1 -> 0. template -struct Invoker1 { +struct Invoker1 { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast(base); return invoker->f_(Unwrap(invoker->p1_)); @@ -481,16 +541,29 @@ struct Invoker1 { // Method: Arity 0 -> 0. template -struct Invoker1 { +struct Invoker1 { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast(base); return (Unwrap(invoker->p1_)->*invoker->f_)(); } }; +// WeakPtr Method: Arity 0 -> 0. +template +struct Invoker1 { + static void DoInvoke(InvokerStorageBase* base) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(); + } +}; + // Function: Arity 2 -> 1. template -struct Invoker1 { +struct Invoker1 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x2) { StorageType* invoker = static_cast(base); @@ -500,7 +573,7 @@ struct Invoker1 { // Method: Arity 1 -> 1. template -struct Invoker1 { +struct Invoker1 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x1) { StorageType* invoker = static_cast(base); @@ -508,10 +581,24 @@ struct Invoker1 { } }; +// WeakPtr Method: Arity 1 -> 1. +template +struct Invoker1 { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits::ForwardType x1) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(x1); + } +}; + // Function: Arity 3 -> 2. template -struct Invoker1 { +struct Invoker1 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x2, typename internal::ParamTraits::ForwardType x3) { @@ -523,7 +610,7 @@ struct Invoker1 { // Method: Arity 2 -> 2. template -struct Invoker1 { +struct Invoker1 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x1, typename internal::ParamTraits::ForwardType x2) { @@ -532,10 +619,25 @@ struct Invoker1 { } }; +// WeakPtr Method: Arity 2 -> 2. +template +struct Invoker1 { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits::ForwardType x1, + typename internal::ParamTraits::ForwardType x2) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(x1, x2); + } +}; + // Function: Arity 4 -> 3. template -struct Invoker1 { +struct Invoker1 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x2, typename internal::ParamTraits::ForwardType x3, @@ -548,7 +650,7 @@ struct Invoker1 { // Method: Arity 3 -> 3. template -struct Invoker1 { +struct Invoker1 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x1, typename internal::ParamTraits::ForwardType x2, @@ -558,10 +660,27 @@ struct Invoker1 { } }; +// WeakPtr Method: Arity 3 -> 3. +template +struct Invoker1 { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits::ForwardType x1, + typename internal::ParamTraits::ForwardType x2, + typename internal::ParamTraits::ForwardType x3) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(x1, x2, x3); + } +}; + // Function: Arity 5 -> 4. template -struct Invoker1 { +struct Invoker1 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x2, typename internal::ParamTraits::ForwardType x3, @@ -575,7 +694,7 @@ struct Invoker1 { // Method: Arity 4 -> 4. template -struct Invoker1 { +struct Invoker1 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x1, typename internal::ParamTraits::ForwardType x2, @@ -586,10 +705,28 @@ struct Invoker1 { } }; +// WeakPtr Method: Arity 4 -> 4. +template +struct Invoker1 { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits::ForwardType x1, + typename internal::ParamTraits::ForwardType x2, + typename internal::ParamTraits::ForwardType x3, + typename internal::ParamTraits::ForwardType x4) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(x1, x2, x3, x4); + } +}; + // Function: Arity 6 -> 5. template -struct Invoker1 { +struct Invoker1 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x2, typename internal::ParamTraits::ForwardType x3, @@ -604,7 +741,7 @@ struct Invoker1 { // Method: Arity 5 -> 5. template -struct Invoker1 { +struct Invoker1 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x1, typename internal::ParamTraits::ForwardType x2, @@ -616,12 +753,31 @@ struct Invoker1 { } }; -template +// WeakPtr Method: Arity 5 -> 5. +template +struct Invoker1 { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits::ForwardType x1, + typename internal::ParamTraits::ForwardType x2, + typename internal::ParamTraits::ForwardType x3, + typename internal::ParamTraits::ForwardType x4, + typename internal::ParamTraits::ForwardType x5) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(x1, x2, x3, x4, x5); + } +}; + +template struct Invoker2; // Function: Arity 2 -> 0. template -struct Invoker2 { +struct Invoker2 { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_)); @@ -630,17 +786,30 @@ struct Invoker2 { // Method: Arity 1 -> 0. template -struct Invoker2 { +struct Invoker2 { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_)); } }; +// WeakPtr Method: Arity 1 -> 0. +template +struct Invoker2 { + static void DoInvoke(InvokerStorageBase* base) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_)); + } +}; + // Function: Arity 3 -> 1. template -struct Invoker2 { +struct Invoker2 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x3) { StorageType* invoker = static_cast(base); @@ -651,7 +820,7 @@ struct Invoker2 { // Method: Arity 2 -> 1. template -struct Invoker2 { +struct Invoker2 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x2) { StorageType* invoker = static_cast(base); @@ -659,10 +828,24 @@ struct Invoker2 { } }; +// WeakPtr Method: Arity 2 -> 1. +template +struct Invoker2 { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits::ForwardType x2) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), x2); + } +}; + // Function: Arity 4 -> 2. template -struct Invoker2 { +struct Invoker2 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x3, typename internal::ParamTraits::ForwardType x4) { @@ -674,7 +857,7 @@ struct Invoker2 { // Method: Arity 3 -> 2. template -struct Invoker2 { +struct Invoker2 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x2, typename internal::ParamTraits::ForwardType x3) { @@ -683,10 +866,26 @@ struct Invoker2 { } }; +// WeakPtr Method: Arity 3 -> 2. +template +struct Invoker2 { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits::ForwardType x2, + typename internal::ParamTraits::ForwardType x3) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), x2, x3); + } +}; + // Function: Arity 5 -> 3. template -struct Invoker2 { +struct Invoker2 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x3, typename internal::ParamTraits::ForwardType x4, @@ -699,7 +898,7 @@ struct Invoker2 { // Method: Arity 4 -> 3. template -struct Invoker2 { +struct Invoker2 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x2, typename internal::ParamTraits::ForwardType x3, @@ -710,10 +909,27 @@ struct Invoker2 { } }; +// WeakPtr Method: Arity 4 -> 3. +template +struct Invoker2 { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits::ForwardType x2, + typename internal::ParamTraits::ForwardType x3, + typename internal::ParamTraits::ForwardType x4) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), x2, x3, x4); + } +}; + // Function: Arity 6 -> 4. template -struct Invoker2 { +struct Invoker2 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x3, typename internal::ParamTraits::ForwardType x4, @@ -728,7 +944,7 @@ struct Invoker2 { // Method: Arity 5 -> 4. template -struct Invoker2 { +struct Invoker2 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x2, typename internal::ParamTraits::ForwardType x3, @@ -740,13 +956,31 @@ struct Invoker2 { } }; -template +// WeakPtr Method: Arity 5 -> 4. +template +struct Invoker2 { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits::ForwardType x2, + typename internal::ParamTraits::ForwardType x3, + typename internal::ParamTraits::ForwardType x4, + typename internal::ParamTraits::ForwardType x5) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), x2, x3, x4, x5); + } +}; + +template struct Invoker3; // Function: Arity 3 -> 0. template -struct Invoker3 { +struct Invoker3 { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), @@ -757,7 +991,7 @@ struct Invoker3 { // Method: Arity 2 -> 0. template -struct Invoker3 { +struct Invoker3 { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), @@ -765,10 +999,23 @@ struct Invoker3 { } }; +// WeakPtr Method: Arity 2 -> 0. +template +struct Invoker3 { + static void DoInvoke(InvokerStorageBase* base) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_)); + } +}; + // Function: Arity 4 -> 1. template -struct Invoker3 { +struct Invoker3 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x4) { StorageType* invoker = static_cast(base); @@ -780,7 +1027,7 @@ struct Invoker3 { // Method: Arity 3 -> 1. template -struct Invoker3 { +struct Invoker3 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x3) { StorageType* invoker = static_cast(base); @@ -789,10 +1036,25 @@ struct Invoker3 { } }; +// WeakPtr Method: Arity 3 -> 1. +template +struct Invoker3 { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits::ForwardType x3) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), x3); + } +}; + // Function: Arity 5 -> 2. template -struct Invoker3 { +struct Invoker3 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x4, typename internal::ParamTraits::ForwardType x5) { @@ -805,7 +1067,7 @@ struct Invoker3 { // Method: Arity 4 -> 2. template -struct Invoker3 { +struct Invoker3 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x3, typename internal::ParamTraits::ForwardType x4) { @@ -815,10 +1077,27 @@ struct Invoker3 { } }; +// WeakPtr Method: Arity 4 -> 2. +template +struct Invoker3 { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits::ForwardType x3, + typename internal::ParamTraits::ForwardType x4) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), x3, + x4); + } +}; + // Function: Arity 6 -> 3. template -struct Invoker3 { +struct Invoker3 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x4, typename internal::ParamTraits::ForwardType x5, @@ -832,7 +1111,7 @@ struct Invoker3 { // Method: Arity 5 -> 3. template -struct Invoker3 { +struct Invoker3 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x3, typename internal::ParamTraits::ForwardType x4, @@ -843,13 +1122,31 @@ struct Invoker3 { } }; -template +// WeakPtr Method: Arity 5 -> 3. +template +struct Invoker3 { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits::ForwardType x3, + typename internal::ParamTraits::ForwardType x4, + typename internal::ParamTraits::ForwardType x5) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), x3, + x4, x5); + } +}; + +template struct Invoker4; // Function: Arity 4 -> 0. template -struct Invoker4 { +struct Invoker4 { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), @@ -860,7 +1157,7 @@ struct Invoker4 { // Method: Arity 3 -> 0. template -struct Invoker4 { +struct Invoker4 { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), @@ -868,10 +1165,25 @@ struct Invoker4 { } }; +// WeakPtr Method: Arity 3 -> 0. +template +struct Invoker4 { + static void DoInvoke(InvokerStorageBase* base) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), + Unwrap(invoker->p4_)); + } +}; + // Function: Arity 5 -> 1. template -struct Invoker4 { +struct Invoker4 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x5) { StorageType* invoker = static_cast(base); @@ -883,7 +1195,7 @@ struct Invoker4 { // Method: Arity 4 -> 1. template -struct Invoker4 { +struct Invoker4 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x4) { StorageType* invoker = static_cast(base); @@ -892,10 +1204,26 @@ struct Invoker4 { } }; +// WeakPtr Method: Arity 4 -> 1. +template +struct Invoker4 { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits::ForwardType x4) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), + Unwrap(invoker->p4_), x4); + } +}; + // Function: Arity 6 -> 2. template -struct Invoker4 { +struct Invoker4 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x5, typename internal::ParamTraits::ForwardType x6) { @@ -908,7 +1236,7 @@ struct Invoker4 { // Method: Arity 5 -> 2. template -struct Invoker4 { +struct Invoker4 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x4, typename internal::ParamTraits::ForwardType x5) { @@ -918,13 +1246,30 @@ struct Invoker4 { } }; -template +// WeakPtr Method: Arity 5 -> 2. +template +struct Invoker4 { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits::ForwardType x4, + typename internal::ParamTraits::ForwardType x5) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), + Unwrap(invoker->p4_), x4, x5); + } +}; + +template struct Invoker5; // Function: Arity 5 -> 0. template -struct Invoker5 { +struct Invoker5 { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), @@ -935,7 +1280,7 @@ struct Invoker5 { // Method: Arity 4 -> 0. template -struct Invoker5 { +struct Invoker5 { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), @@ -943,10 +1288,25 @@ struct Invoker5 { } }; +// WeakPtr Method: Arity 4 -> 0. +template +struct Invoker5 { + static void DoInvoke(InvokerStorageBase* base) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), + Unwrap(invoker->p4_), Unwrap(invoker->p5_)); + } +}; + // Function: Arity 6 -> 1. template -struct Invoker5 { +struct Invoker5 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x6) { StorageType* invoker = static_cast(base); @@ -958,7 +1318,7 @@ struct Invoker5 { // Method: Arity 5 -> 1. template -struct Invoker5 { +struct Invoker5 { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits::ForwardType x5) { StorageType* invoker = static_cast(base); @@ -967,13 +1327,29 @@ struct Invoker5 { } }; -template +// WeakPtr Method: Arity 5 -> 1. +template +struct Invoker5 { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits::ForwardType x5) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), + Unwrap(invoker->p4_), Unwrap(invoker->p5_), x5); + } +}; + +template struct Invoker6; // Function: Arity 6 -> 0. template -struct Invoker6 { +struct Invoker6 { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), @@ -985,7 +1361,7 @@ struct Invoker6 { // Method: Arity 5 -> 0. template -struct Invoker6 { +struct Invoker6 { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), @@ -994,6 +1370,20 @@ struct Invoker6 { } }; +// WeakPtr Method: Arity 5 -> 0. +template +struct Invoker6 { + static void DoInvoke(InvokerStorageBase* base) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_), + Unwrap(invoker->p4_), Unwrap(invoker->p5_), Unwrap(invoker->p6_)); + } +}; // InvokerStorageN<> // @@ -1014,8 +1404,10 @@ class InvokerStorage0 : public InvokerStorageBase { public: typedef InvokerStorage0 StorageType; typedef FunctionTraits TargetTraits; - typedef Invoker0 Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + typedef Invoker0 Invoker; @@ -1033,8 +1425,14 @@ class InvokerStorage1 : public InvokerStorageBase { public: typedef InvokerStorage1 StorageType; typedef FunctionTraits TargetTraits; - typedef Invoker1 Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + typedef ParamTraits P1Traits; + typedef Invoker1::value, StorageType, + typename TargetTraits::NormalizedSig> Invoker; + COMPILE_ASSERT(!(IsWeakMethod::value) || + is_void::value, + weak_ptrs_can_only_bind_to_methods_without_return_values); // For methods, we need to be careful for parameter 1. We skip the // scoped_refptr check because the binder itself takes care of this. We also @@ -1073,8 +1471,15 @@ class InvokerStorage2 : public InvokerStorageBase { public: typedef InvokerStorage2 StorageType; typedef FunctionTraits TargetTraits; - typedef Invoker2 Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + typedef ParamTraits P1Traits; + typedef ParamTraits P2Traits; + typedef Invoker2::value, StorageType, + typename TargetTraits::NormalizedSig> Invoker; + COMPILE_ASSERT(!(IsWeakMethod::value) || + is_void::value, + weak_ptrs_can_only_bind_to_methods_without_return_values); // For methods, we need to be careful for parameter 1. We skip the // scoped_refptr check because the binder itself takes care of this. We also @@ -1118,8 +1523,16 @@ class InvokerStorage3 : public InvokerStorageBase { public: typedef InvokerStorage3 StorageType; typedef FunctionTraits TargetTraits; - typedef Invoker3 Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + typedef ParamTraits P1Traits; + typedef ParamTraits P2Traits; + typedef ParamTraits P3Traits; + typedef Invoker3::value, StorageType, + typename TargetTraits::NormalizedSig> Invoker; + COMPILE_ASSERT(!(IsWeakMethod::value) || + is_void::value, + weak_ptrs_can_only_bind_to_methods_without_return_values); // For methods, we need to be careful for parameter 1. We skip the // scoped_refptr check because the binder itself takes care of this. We also @@ -1168,8 +1581,17 @@ class InvokerStorage4 : public InvokerStorageBase { public: typedef InvokerStorage4 StorageType; typedef FunctionTraits TargetTraits; - typedef Invoker4 Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + typedef ParamTraits P1Traits; + typedef ParamTraits P2Traits; + typedef ParamTraits P3Traits; + typedef ParamTraits P4Traits; + typedef Invoker4::value, StorageType, + typename TargetTraits::NormalizedSig> Invoker; + COMPILE_ASSERT(!(IsWeakMethod::value) || + is_void::value, + weak_ptrs_can_only_bind_to_methods_without_return_values); // For methods, we need to be careful for parameter 1. We skip the // scoped_refptr check because the binder itself takes care of this. We also @@ -1224,8 +1646,18 @@ class InvokerStorage5 : public InvokerStorageBase { public: typedef InvokerStorage5 StorageType; typedef FunctionTraits TargetTraits; - typedef Invoker5 Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + typedef ParamTraits P1Traits; + typedef ParamTraits P2Traits; + typedef ParamTraits P3Traits; + typedef ParamTraits P4Traits; + typedef ParamTraits P5Traits; + typedef Invoker5::value, StorageType, + typename TargetTraits::NormalizedSig> Invoker; + COMPILE_ASSERT(!(IsWeakMethod::value) || + is_void::value, + weak_ptrs_can_only_bind_to_methods_without_return_values); // For methods, we need to be careful for parameter 1. We skip the // scoped_refptr check because the binder itself takes care of this. We also @@ -1286,8 +1718,19 @@ class InvokerStorage6 : public InvokerStorageBase { public: typedef InvokerStorage6 StorageType; typedef FunctionTraits TargetTraits; - typedef Invoker6 Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + typedef ParamTraits P1Traits; + typedef ParamTraits P2Traits; + typedef ParamTraits P3Traits; + typedef ParamTraits P4Traits; + typedef ParamTraits P5Traits; + typedef ParamTraits P6Traits; + typedef Invoker6::value, StorageType, + typename TargetTraits::NormalizedSig> Invoker; + COMPILE_ASSERT(!(IsWeakMethod::value) || + is_void::value, + weak_ptrs_can_only_bind_to_methods_without_return_values); // For methods, we need to be careful for parameter 1. We skip the // scoped_refptr check because the binder itself takes care of this. We also diff --git a/base/bind_internal.h.pump b/base/bind_internal.h.pump index 4ccec5e..85875de 100644 --- a/base/bind_internal.h.pump +++ b/base/bind_internal.h.pump @@ -17,6 +17,7 @@ $var MAX_ARITY = 6 #include "base/bind_helpers.h" #include "base/callback_internal.h" +#include "base/memory/weak_ptr.h" #include "base/template_util.h" #include "build/build_config.h" @@ -42,10 +43,21 @@ namespace internal { // a calback. // InvokerStorageN<> -- Provides storage for the bound parameters, and // typedefs to the above. +// IsWeakMethod<> -- Determines if we are binding a method to a WeakPtr<>. // // More details about the design of each class is included in a comment closer // to their defition. + +// IsWeakMethod determines if we are binding a method to a WeakPtr<> for an +// object. It is used to select an InvokerN that will no-op itself in the +// event the WeakPtr<> for the target object is invalidated. +template +struct IsWeakMethod : public false_type {}; + +template +struct IsWeakMethod > : public true_type {}; + // FunctionTraits<> // // The FunctionTraits<> template determines the type of function, and also @@ -83,6 +95,8 @@ struct FunctionTraits { typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]); typedef false_type IsMethod; + typedef R Return; + $if ARITY > 0 [[ // Target type for each bound parameter. @@ -102,6 +116,8 @@ struct FunctionTraits { typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; @@ -119,6 +135,8 @@ struct FunctionTraits { typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]); typedef true_type IsMethod; + typedef R Return; + // Target type for each bound parameter. typedef T B1; @@ -154,7 +172,7 @@ $for ARG [[ $range BOUND 0..MAX_ARITY $for BOUND [[ -template +template struct Invoker$(BOUND); $range ARITY 0..MAX_ARITY @@ -179,7 +197,7 @@ $range M_UNBOUND_ARG (M_ARITY - UNBOUND + 1)..M_ARITY template 0 [[,]][[]] $for ARG , [[typename X$(ARG)]]> -struct Invoker$(BOUND) { +struct Invoker$(BOUND) { static R DoInvoke(InvokerStorageBase* base[[]] $if UNBOUND != 0 [[, ]][[]] $for UNBOUND_ARG , [[typename internal::ParamTraits::ForwardType x$(UNBOUND_ARG)]]) { @@ -196,7 +214,7 @@ $if BOUND > 0 [[ // Method: Arity $(M_ARITY) -> $(UNBOUND). template 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]> -struct Invoker$(BOUND) { +struct Invoker$(BOUND) { static R DoInvoke(InvokerStorageBase* base[[]] $if UNBOUND > 0 [[, ]][[]] $for M_UNBOUND_ARG , [[typename internal::ParamTraits::ForwardType x$(M_UNBOUND_ARG)]]) { @@ -208,13 +226,31 @@ $for M_UNBOUND_ARG , [[x$(M_UNBOUND_ARG)]]); } }; +// WeakPtr Method: Arity $(M_ARITY) -> $(UNBOUND). +template 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]> +struct Invoker$(BOUND) { + static void DoInvoke(InvokerStorageBase* base[[]] +$if UNBOUND > 0 [[, ]][[]] +$for M_UNBOUND_ARG , [[typename internal::ParamTraits::ForwardType x$(M_UNBOUND_ARG)]]) { + StorageType* invoker = static_cast(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)([[]] +$for M_BOUND_ARG , [[Unwrap(invoker->p$(M_BOUND_ARG)_)]][[]] +$if UNBOUND > 0 [[$if BOUND > 1 [[, ]]]][[]] +$for M_UNBOUND_ARG , [[x$(M_UNBOUND_ARG)]]); + } +}; + ]] $$ if BOUND ]] $$ if UNBOUND ]] $$ for ARITY ]] $$ for BOUND - // InvokerStorageN<> // // These are the actual storage classes for the Invokers. @@ -239,8 +275,25 @@ class InvokerStorage$(BOUND) : public InvokerStorageBase { public: typedef InvokerStorage$(BOUND) StorageType; typedef FunctionTraits TargetTraits; - typedef Invoker$(BOUND) Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + +$for BOUND_ARG [[ + typedef ParamTraits P$(BOUND_ARG)Traits; + +]] + +$if BOUND == 0 [[ + typedef Invoker$(BOUND) Invoker; +]] $else [[ + typedef Invoker$(BOUND)::value, StorageType, + typename TargetTraits::NormalizedSig> Invoker; + COMPILE_ASSERT(!(IsWeakMethod::value) || + is_void::value, + weak_ptrs_can_only_bind_to_methods_without_return_values); +]] + $for BOUND_ARG [[ $if BOUND_ARG == 1 [[ diff --git a/base/bind_internal_win.h b/base/bind_internal_win.h index 85ba2ae..250f472 100644 --- a/base/bind_internal_win.h +++ b/base/bind_internal_win.h @@ -31,6 +31,8 @@ template struct FunctionTraits { typedef R (*NormalizedSig)(); typedef false_type IsMethod; + + typedef R Return; }; // __fastcall Function: Arity 0. @@ -38,6 +40,8 @@ template struct FunctionTraits { typedef R (*NormalizedSig)(); typedef false_type IsMethod; + + typedef R Return; }; // __stdcall Function: Arity 1. @@ -45,6 +49,9 @@ template struct FunctionTraits { typedef R (*NormalizedSig)(X1); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; }; @@ -54,6 +61,9 @@ template struct FunctionTraits { typedef R (*NormalizedSig)(X1); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; }; @@ -63,6 +73,9 @@ template struct FunctionTraits { typedef R (*NormalizedSig)(X1, X2); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -73,6 +86,9 @@ template struct FunctionTraits { typedef R (*NormalizedSig)(X1, X2); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -83,6 +99,9 @@ template struct FunctionTraits { typedef R (*NormalizedSig)(X1, X2, X3); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -94,6 +113,9 @@ template struct FunctionTraits { typedef R (*NormalizedSig)(X1, X2, X3); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -105,6 +127,9 @@ template struct FunctionTraits { typedef R (*NormalizedSig)(X1, X2, X3, X4); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -117,6 +142,9 @@ template struct FunctionTraits { typedef R (*NormalizedSig)(X1, X2, X3, X4); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -130,6 +158,9 @@ template { typedef R (*NormalizedSig)(X1, X2, X3, X4, X5); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -144,6 +175,9 @@ template { typedef R (*NormalizedSig)(X1, X2, X3, X4, X5); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -158,6 +192,9 @@ template { typedef R (*NormalizedSig)(X1, X2, X3, X4, X5, X6); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; @@ -173,6 +210,9 @@ template { typedef R (*NormalizedSig)(X1, X2, X3, X4, X5, X6); typedef false_type IsMethod; + + typedef R Return; + // Target type for each bound parameter. typedef X1 B1; typedef X2 B2; diff --git a/base/bind_internal_win.h.pump b/base/bind_internal_win.h.pump index d293fcc..80ee37d 100644 --- a/base/bind_internal_win.h.pump +++ b/base/bind_internal_win.h.pump @@ -40,6 +40,8 @@ struct FunctionTraits { typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]); typedef false_type IsMethod; + typedef R Return; + $if ARITY > 0 [[ // Target type for each bound parameter. @@ -58,6 +60,8 @@ struct FunctionTraits { typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]); typedef false_type IsMethod; + typedef R Return; + $if ARITY > 0 [[ // Target type for each bound parameter. diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc index c131a86..d57f3d0 100644 --- a/base/bind_unittest.cc +++ b/base/bind_unittest.cc @@ -183,6 +183,10 @@ void RefArgSet(int &n) { n = 2; } +int FunctionWithWeakFirstParam(WeakPtr o, int n) { + return n; +} + // Only useful in no-compile tests. int UnwrapNoRefParentRef(Parent& p) { return p.value; @@ -451,7 +455,7 @@ TEST_F(BindTest, SupportsAddRefAndRelease) { } // Unretained() wrapper support. -// - Method bound to Unretained() non-object. +// - Method bound to Unretained() non-const object. // - Const method bound to Unretained() non-const object. // - Const method bound to Unretained() const object. TEST_F(BindTest, Unretained) { @@ -471,6 +475,46 @@ TEST_F(BindTest, Unretained) { const_method_const_ptr_cb.Run(); } +// WeakPtr() support. +// - Method bound to WeakPtr<> to non-const object. +// - Const method bound to WeakPtr<> to non-const object. +// - Const method bound to WeakPtr<> to const object. +// - Normal Function with WeakPtr<> as P1 can have return type and is +// not canceled. +TEST_F(BindTest, WeakPtr) { + EXPECT_CALL(no_ref_, VoidMethod0()); + EXPECT_CALL(no_ref_, VoidConstMethod0()).Times(2); + + WeakPtrFactory weak_factory(&no_ref_); + WeakPtrFactory const_weak_factory(const_no_ref_ptr_); + + Callback method_cb = + Bind(&NoRef::VoidMethod0, weak_factory.GetWeakPtr()); + method_cb.Run(); + + Callback const_method_cb = + Bind(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr()); + const_method_cb.Run(); + + Callback const_method_const_ptr_cb = + Bind(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr()); + const_method_const_ptr_cb.Run(); + + Callback normal_func_cb = + Bind(&FunctionWithWeakFirstParam, weak_factory.GetWeakPtr()); + EXPECT_EQ(1, normal_func_cb.Run(1)); + + weak_factory.InvalidateWeakPtrs(); + const_weak_factory.InvalidateWeakPtrs(); + + method_cb.Run(); + const_method_cb.Run(); + const_method_const_ptr_cb.Run(); + + // Still runs even after the pointers are invalidated. + EXPECT_EQ(2, normal_func_cb.Run(2)); +} + // ConstRef() wrapper support. // - Binding w/o ConstRef takes a copy. // - Binding a ConstRef takes a reference. @@ -627,6 +671,12 @@ TEST_F(BindTest, NoCompile) { // Callback ref_count_as_raw_ptr = // Bind(&VoidPolymorphic1, &for_raw_ptr); + // - WeakPtrs cannot be bound to methods with return types. + // HasRef for_raw_ptr; + // WeakPtrFactory weak_factory(&no_ref_); + // Callback weak_ptr_with_non_void_return_type = + // Bind(&NoRef::IntMethod0, weak_factory.GetWeakPtr()); + } #if defined(OS_WIN) diff --git a/base/callback.h b/base/callback.h index 983fa7b02..fbd81d8 100644 --- a/base/callback.h +++ b/base/callback.h @@ -49,7 +49,7 @@ // // void PrintHi() { LOG(INFO) << "hi."; } // base::Closure void_func_cb = base::Bind(&PrintHi); -// LOG(INFO) << void_func_cb.Run(); // Prints: hi. +// void_func_cb.Run(); // Prints: hi. // // /* Binding a class method. */ // class Ref : public RefCountedThreadSafe { diff --git a/base/callback.h.pump b/base/callback.h.pump index b565e38..cc45dd7 100644 --- a/base/callback.h.pump +++ b/base/callback.h.pump @@ -47,12 +47,12 @@ $var MAX_ARITY = 6 // // /* Binding a normal function. */ // int Return5() { return 5; } -// base::Callback func_cb = base::Bind(&Return5); -// LOG(INFO) << func_cb.Run(5); // Prints 5. +// base::Callback func_cb = base::Bind(&Return5); +// LOG(INFO) << func_cb.Run(); // Prints 5. // // void PrintHi() { LOG(INFO) << "hi."; } // base::Closure void_func_cb = base::Bind(&PrintHi); -// LOG(INFO) << void_func_cb.Run(); // Prints: hi. +// void_func_cb.Run(); // Prints: hi. // // /* Binding a class method. */ // class Ref : public RefCountedThreadSafe { @@ -191,7 +191,7 @@ $var MAX_ARITY = 6 // // These are not features that are required in Chromium. Some of them, such as // allowing for reference parameters, and subtyping of functions, may actually -// because a source of errors. Removing support for these features actually +// become a source of errors. Removing support for these features actually // allows for a simpler implementation, and a terser Currying API. // // diff --git a/base/template_util.h b/base/template_util.h index e48af91..66e6a61 100644 --- a/base/template_util.h +++ b/base/template_util.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// 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. @@ -37,6 +37,9 @@ template struct is_non_const_reference : false_type {}; template struct is_non_const_reference : true_type {}; template struct is_non_const_reference : false_type {}; +template struct is_void : false_type {}; +template <> struct is_void : true_type {}; + namespace internal { // Types YesType and NoType are guaranteed such that sizeof(YesType) < -- cgit v1.1