diff options
author | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-16 22:35:14 +0000 |
---|---|---|
committer | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-16 22:35:14 +0000 |
commit | 935405891d4f2cb40c4fe287e3e4c06ade5c38ce (patch) | |
tree | d71dd33fe46eeddb200d92dda1d02c9c0b8a7c10 | |
parent | 409dc6ef2d6095d71f6ea4f59b07106b91626d24 (diff) | |
download | chromium_src-935405891d4f2cb40c4fe287e3e4c06ade5c38ce.zip chromium_src-935405891d4f2cb40c4fe287e3e4c06ade5c38ce.tar.gz chromium_src-935405891d4f2cb40c4fe287e3e4c06ade5c38ce.tar.bz2 |
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
-rw-r--r-- | base/bind_helpers.h | 9 | ||||
-rw-r--r-- | base/bind_internal.h | 569 | ||||
-rw-r--r-- | base/bind_internal.h.pump | 63 | ||||
-rw-r--r-- | base/bind_internal_win.h | 40 | ||||
-rw-r--r-- | base/bind_internal_win.h.pump | 4 | ||||
-rw-r--r-- | base/bind_unittest.cc | 52 | ||||
-rw-r--r-- | base/callback.h | 2 | ||||
-rw-r--r-- | base/callback.h.pump | 8 | ||||
-rw-r--r-- | 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<T> const_ref) { // Utility for handling different refcounting semantics in the Bind() // function. -template <typename ref, typename T> +template <typename IsMethod, typename T> struct MaybeRefcount; template <typename T> @@ -248,6 +249,12 @@ struct MaybeRefcount<base::true_type, const T*> { static void Release(const T* o) { o->Release(); } }; +template <typename T> +struct MaybeRefcount<base::true_type, WeakPtr<T> > { + static void AddRef(const WeakPtr<T>&) {} + static void Release(const WeakPtr<T>&) {} +}; + } // namespace internal template <typename T> 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 <bool IsMethod, typename T> +struct IsWeakMethod : public false_type {}; + +template <typename T> +struct IsWeakMethod<true, WeakPtr<T> > : public true_type {}; + // FunctionTraits<> // // The FunctionTraits<> template determines the type of function, and also @@ -75,6 +87,8 @@ struct FunctionTraits<R(*)()> { typedef R (*NormalizedSig)(); typedef false_type IsMethod; + typedef R Return; + }; // Method: Arity 0. @@ -83,6 +97,8 @@ struct FunctionTraits<R(T::*)()> { 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<R(T::*)() const> { 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 <typename R, typename X1> struct FunctionTraits<R(*)(X1)> { 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<R(T::*)(X1)> { 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<R(T::*)(X1) const> { 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 <typename R, typename X1, typename X2> struct FunctionTraits<R(*)(X1, X2)> { 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<R(T::*)(X1, X2)> { 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<R(T::*)(X1, X2) const> { 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 <typename R, typename X1, typename X2, typename X3> struct FunctionTraits<R(*)(X1, X2, X3)> { 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<R(T::*)(X1, X2, X3)> { 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<R(T::*)(X1, X2, X3) const> { 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 <typename R, typename X1, typename X2, typename X3, typename X4> struct FunctionTraits<R(*)(X1, X2, X3, X4)> { 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<R(T::*)(X1, X2, X3, X4)> { 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<R(T::*)(X1, X2, X3, X4) const> { 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 <typename R, typename X1, typename X2, typename X3, typename X4, struct FunctionTraits<R(*)(X1, X2, X3, X4, X5)> { 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<R(T::*)(X1, X2, X3, X4, X5)> { 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<R(T::*)(X1, X2, X3, X4, X5) const> { 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 <typename R, typename X1, typename X2, typename X3, typename X4, struct FunctionTraits<R(*)(X1, X2, X3, X4, X5, X6)> { 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<R(T::*)(X1, X2, X3, X4, X5, X6)> { 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<R(T::*)(X1, X2, X3, X4, X5, X6) const> { 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<R(T::*)(X1, X2, X3, X4, X5, X6) const> { // templates classes in the system to only have as many specializations as // the max arity of function we wish to support. -template <typename StorageType, typename NormalizedSig> +template <bool IsWeak, typename StorageType, typename NormalizedSig> struct Invoker0; // Function: Arity 0 -> 0. template <typename StorageType, typename R> -struct Invoker0<StorageType, R(*)()> { +struct Invoker0<false, StorageType, R(*)()> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(); @@ -390,7 +450,7 @@ struct Invoker0<StorageType, R(*)()> { // Function: Arity 1 -> 1. template <typename StorageType, typename R,typename X1> -struct Invoker0<StorageType, R(*)(X1)> { +struct Invoker0<false, StorageType, R(*)(X1)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1) { StorageType* invoker = static_cast<StorageType*>(base); @@ -400,7 +460,7 @@ struct Invoker0<StorageType, R(*)(X1)> { // Function: Arity 2 -> 2. template <typename StorageType, typename R,typename X1, typename X2> -struct Invoker0<StorageType, R(*)(X1, X2)> { +struct Invoker0<false, StorageType, R(*)(X1, X2)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1, typename internal::ParamTraits<X2>::ForwardType x2) { @@ -412,7 +472,7 @@ struct Invoker0<StorageType, R(*)(X1, X2)> { // Function: Arity 3 -> 3. template <typename StorageType, typename R,typename X1, typename X2, typename X3> -struct Invoker0<StorageType, R(*)(X1, X2, X3)> { +struct Invoker0<false, StorageType, R(*)(X1, X2, X3)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1, typename internal::ParamTraits<X2>::ForwardType x2, @@ -425,7 +485,7 @@ struct Invoker0<StorageType, R(*)(X1, X2, X3)> { // Function: Arity 4 -> 4. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4> -struct Invoker0<StorageType, R(*)(X1, X2, X3, X4)> { +struct Invoker0<false, StorageType, R(*)(X1, X2, X3, X4)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1, typename internal::ParamTraits<X2>::ForwardType x2, @@ -439,7 +499,7 @@ struct Invoker0<StorageType, R(*)(X1, X2, X3, X4)> { // Function: Arity 5 -> 5. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker0<StorageType, R(*)(X1, X2, X3, X4, X5)> { +struct Invoker0<false, StorageType, R(*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1, typename internal::ParamTraits<X2>::ForwardType x2, @@ -454,7 +514,7 @@ struct Invoker0<StorageType, R(*)(X1, X2, X3, X4, X5)> { // Function: Arity 6 -> 6. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> -struct Invoker0<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { +struct Invoker0<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1, typename internal::ParamTraits<X2>::ForwardType x2, @@ -467,12 +527,12 @@ struct Invoker0<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { } }; -template <typename StorageType, typename NormalizedSig> +template <bool IsWeak, typename StorageType, typename NormalizedSig> struct Invoker1; // Function: Arity 1 -> 0. template <typename StorageType, typename R,typename X1> -struct Invoker1<StorageType, R(*)(X1)> { +struct Invoker1<false, StorageType, R(*)(X1)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_)); @@ -481,16 +541,29 @@ struct Invoker1<StorageType, R(*)(X1)> { // Method: Arity 0 -> 0. template <typename StorageType, typename R, typename T> -struct Invoker1<StorageType, R(T::*)()> { +struct Invoker1<false, StorageType, R(T::*)()> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(); } }; +// WeakPtr Method: Arity 0 -> 0. +template <typename StorageType, typename T> +struct Invoker1<true, StorageType, void(T::*)()> { + static void DoInvoke(InvokerStorageBase* base) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(); + } +}; + // Function: Arity 2 -> 1. template <typename StorageType, typename R,typename X1, typename X2> -struct Invoker1<StorageType, R(*)(X1, X2)> { +struct Invoker1<false, StorageType, R(*)(X1, X2)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X2>::ForwardType x2) { StorageType* invoker = static_cast<StorageType*>(base); @@ -500,7 +573,7 @@ struct Invoker1<StorageType, R(*)(X1, X2)> { // Method: Arity 1 -> 1. template <typename StorageType, typename R, typename T, typename X1> -struct Invoker1<StorageType, R(T::*)(X1)> { +struct Invoker1<false, StorageType, R(T::*)(X1)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1) { StorageType* invoker = static_cast<StorageType*>(base); @@ -508,10 +581,24 @@ struct Invoker1<StorageType, R(T::*)(X1)> { } }; +// WeakPtr Method: Arity 1 -> 1. +template <typename StorageType, typename T, typename X1> +struct Invoker1<true, StorageType, void(T::*)(X1)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(x1); + } +}; + // Function: Arity 3 -> 2. template <typename StorageType, typename R,typename X1, typename X2, typename X3> -struct Invoker1<StorageType, R(*)(X1, X2, X3)> { +struct Invoker1<false, StorageType, R(*)(X1, X2, X3)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X2>::ForwardType x2, typename internal::ParamTraits<X3>::ForwardType x3) { @@ -523,7 +610,7 @@ struct Invoker1<StorageType, R(*)(X1, X2, X3)> { // Method: Arity 2 -> 2. template <typename StorageType, typename R, typename T, typename X1, typename X2> -struct Invoker1<StorageType, R(T::*)(X1, X2)> { +struct Invoker1<false, StorageType, R(T::*)(X1, X2)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1, typename internal::ParamTraits<X2>::ForwardType x2) { @@ -532,10 +619,25 @@ struct Invoker1<StorageType, R(T::*)(X1, X2)> { } }; +// WeakPtr Method: Arity 2 -> 2. +template <typename StorageType, typename T, typename X1, typename X2> +struct Invoker1<true, StorageType, void(T::*)(X1, X2)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1, + typename internal::ParamTraits<X2>::ForwardType x2) { + StorageType* invoker = static_cast<StorageType*>(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 <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4> -struct Invoker1<StorageType, R(*)(X1, X2, X3, X4)> { +struct Invoker1<false, StorageType, R(*)(X1, X2, X3, X4)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X2>::ForwardType x2, typename internal::ParamTraits<X3>::ForwardType x3, @@ -548,7 +650,7 @@ struct Invoker1<StorageType, R(*)(X1, X2, X3, X4)> { // Method: Arity 3 -> 3. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3> -struct Invoker1<StorageType, R(T::*)(X1, X2, X3)> { +struct Invoker1<false, StorageType, R(T::*)(X1, X2, X3)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1, typename internal::ParamTraits<X2>::ForwardType x2, @@ -558,10 +660,27 @@ struct Invoker1<StorageType, R(T::*)(X1, X2, X3)> { } }; +// WeakPtr Method: Arity 3 -> 3. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3> +struct Invoker1<true, StorageType, void(T::*)(X1, X2, X3)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3) { + StorageType* invoker = static_cast<StorageType*>(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 <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker1<StorageType, R(*)(X1, X2, X3, X4, X5)> { +struct Invoker1<false, StorageType, R(*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X2>::ForwardType x2, typename internal::ParamTraits<X3>::ForwardType x3, @@ -575,7 +694,7 @@ struct Invoker1<StorageType, R(*)(X1, X2, X3, X4, X5)> { // Method: Arity 4 -> 4. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4> -struct Invoker1<StorageType, R(T::*)(X1, X2, X3, X4)> { +struct Invoker1<false, StorageType, R(T::*)(X1, X2, X3, X4)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1, typename internal::ParamTraits<X2>::ForwardType x2, @@ -586,10 +705,28 @@ struct Invoker1<StorageType, R(T::*)(X1, X2, X3, X4)> { } }; +// WeakPtr Method: Arity 4 -> 4. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4> +struct Invoker1<true, StorageType, void(T::*)(X1, X2, X3, X4)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4) { + StorageType* invoker = static_cast<StorageType*>(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 <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> -struct Invoker1<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { +struct Invoker1<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X2>::ForwardType x2, typename internal::ParamTraits<X3>::ForwardType x3, @@ -604,7 +741,7 @@ struct Invoker1<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { // Method: Arity 5 -> 5. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker1<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { +struct Invoker1<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X1>::ForwardType x1, typename internal::ParamTraits<X2>::ForwardType x2, @@ -616,12 +753,31 @@ struct Invoker1<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { } }; -template <typename StorageType, typename NormalizedSig> +// WeakPtr Method: Arity 5 -> 5. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4, typename X5> +struct Invoker1<true, StorageType, void(T::*)(X1, X2, X3, X4, X5)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X1>::ForwardType x1, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5) { + StorageType* invoker = static_cast<StorageType*>(base); + typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; + if (!weak_ptr.get()) { + return; + } + (weak_ptr->*invoker->f_)(x1, x2, x3, x4, x5); + } +}; + +template <bool IsWeak, typename StorageType, typename NormalizedSig> struct Invoker2; // Function: Arity 2 -> 0. template <typename StorageType, typename R,typename X1, typename X2> -struct Invoker2<StorageType, R(*)(X1, X2)> { +struct Invoker2<false, StorageType, R(*)(X1, X2)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_)); @@ -630,17 +786,30 @@ struct Invoker2<StorageType, R(*)(X1, X2)> { // Method: Arity 1 -> 0. template <typename StorageType, typename R, typename T, typename X1> -struct Invoker2<StorageType, R(T::*)(X1)> { +struct Invoker2<false, StorageType, R(T::*)(X1)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_)); } }; +// WeakPtr Method: Arity 1 -> 0. +template <typename StorageType, typename T, typename X1> +struct Invoker2<true, StorageType, void(T::*)(X1)> { + static void DoInvoke(InvokerStorageBase* base) { + StorageType* invoker = static_cast<StorageType*>(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 <typename StorageType, typename R,typename X1, typename X2, typename X3> -struct Invoker2<StorageType, R(*)(X1, X2, X3)> { +struct Invoker2<false, StorageType, R(*)(X1, X2, X3)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X3>::ForwardType x3) { StorageType* invoker = static_cast<StorageType*>(base); @@ -651,7 +820,7 @@ struct Invoker2<StorageType, R(*)(X1, X2, X3)> { // Method: Arity 2 -> 1. template <typename StorageType, typename R, typename T, typename X1, typename X2> -struct Invoker2<StorageType, R(T::*)(X1, X2)> { +struct Invoker2<false, StorageType, R(T::*)(X1, X2)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X2>::ForwardType x2) { StorageType* invoker = static_cast<StorageType*>(base); @@ -659,10 +828,24 @@ struct Invoker2<StorageType, R(T::*)(X1, X2)> { } }; +// WeakPtr Method: Arity 2 -> 1. +template <typename StorageType, typename T, typename X1, typename X2> +struct Invoker2<true, StorageType, void(T::*)(X1, X2)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X2>::ForwardType x2) { + StorageType* invoker = static_cast<StorageType*>(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 <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4> -struct Invoker2<StorageType, R(*)(X1, X2, X3, X4)> { +struct Invoker2<false, StorageType, R(*)(X1, X2, X3, X4)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X3>::ForwardType x3, typename internal::ParamTraits<X4>::ForwardType x4) { @@ -674,7 +857,7 @@ struct Invoker2<StorageType, R(*)(X1, X2, X3, X4)> { // Method: Arity 3 -> 2. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3> -struct Invoker2<StorageType, R(T::*)(X1, X2, X3)> { +struct Invoker2<false, StorageType, R(T::*)(X1, X2, X3)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X2>::ForwardType x2, typename internal::ParamTraits<X3>::ForwardType x3) { @@ -683,10 +866,26 @@ struct Invoker2<StorageType, R(T::*)(X1, X2, X3)> { } }; +// WeakPtr Method: Arity 3 -> 2. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3> +struct Invoker2<true, StorageType, void(T::*)(X1, X2, X3)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3) { + StorageType* invoker = static_cast<StorageType*>(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 <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker2<StorageType, R(*)(X1, X2, X3, X4, X5)> { +struct Invoker2<false, StorageType, R(*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X3>::ForwardType x3, typename internal::ParamTraits<X4>::ForwardType x4, @@ -699,7 +898,7 @@ struct Invoker2<StorageType, R(*)(X1, X2, X3, X4, X5)> { // Method: Arity 4 -> 3. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4> -struct Invoker2<StorageType, R(T::*)(X1, X2, X3, X4)> { +struct Invoker2<false, StorageType, R(T::*)(X1, X2, X3, X4)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X2>::ForwardType x2, typename internal::ParamTraits<X3>::ForwardType x3, @@ -710,10 +909,27 @@ struct Invoker2<StorageType, R(T::*)(X1, X2, X3, X4)> { } }; +// WeakPtr Method: Arity 4 -> 3. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4> +struct Invoker2<true, StorageType, void(T::*)(X1, X2, X3, X4)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4) { + StorageType* invoker = static_cast<StorageType*>(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 <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> -struct Invoker2<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { +struct Invoker2<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X3>::ForwardType x3, typename internal::ParamTraits<X4>::ForwardType x4, @@ -728,7 +944,7 @@ struct Invoker2<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { // Method: Arity 5 -> 4. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker2<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { +struct Invoker2<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X2>::ForwardType x2, typename internal::ParamTraits<X3>::ForwardType x3, @@ -740,13 +956,31 @@ struct Invoker2<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { } }; -template <typename StorageType, typename NormalizedSig> +// WeakPtr Method: Arity 5 -> 4. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4, typename X5> +struct Invoker2<true, StorageType, void(T::*)(X1, X2, X3, X4, X5)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X2>::ForwardType x2, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5) { + StorageType* invoker = static_cast<StorageType*>(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 <bool IsWeak, typename StorageType, typename NormalizedSig> struct Invoker3; // Function: Arity 3 -> 0. template <typename StorageType, typename R,typename X1, typename X2, typename X3> -struct Invoker3<StorageType, R(*)(X1, X2, X3)> { +struct Invoker3<false, StorageType, R(*)(X1, X2, X3)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), @@ -757,7 +991,7 @@ struct Invoker3<StorageType, R(*)(X1, X2, X3)> { // Method: Arity 2 -> 0. template <typename StorageType, typename R, typename T, typename X1, typename X2> -struct Invoker3<StorageType, R(T::*)(X1, X2)> { +struct Invoker3<false, StorageType, R(T::*)(X1, X2)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), @@ -765,10 +999,23 @@ struct Invoker3<StorageType, R(T::*)(X1, X2)> { } }; +// WeakPtr Method: Arity 2 -> 0. +template <typename StorageType, typename T, typename X1, typename X2> +struct Invoker3<true, StorageType, void(T::*)(X1, X2)> { + static void DoInvoke(InvokerStorageBase* base) { + StorageType* invoker = static_cast<StorageType*>(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 <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4> -struct Invoker3<StorageType, R(*)(X1, X2, X3, X4)> { +struct Invoker3<false, StorageType, R(*)(X1, X2, X3, X4)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X4>::ForwardType x4) { StorageType* invoker = static_cast<StorageType*>(base); @@ -780,7 +1027,7 @@ struct Invoker3<StorageType, R(*)(X1, X2, X3, X4)> { // Method: Arity 3 -> 1. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3> -struct Invoker3<StorageType, R(T::*)(X1, X2, X3)> { +struct Invoker3<false, StorageType, R(T::*)(X1, X2, X3)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X3>::ForwardType x3) { StorageType* invoker = static_cast<StorageType*>(base); @@ -789,10 +1036,25 @@ struct Invoker3<StorageType, R(T::*)(X1, X2, X3)> { } }; +// WeakPtr Method: Arity 3 -> 1. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3> +struct Invoker3<true, StorageType, void(T::*)(X1, X2, X3)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X3>::ForwardType x3) { + StorageType* invoker = static_cast<StorageType*>(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 <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker3<StorageType, R(*)(X1, X2, X3, X4, X5)> { +struct Invoker3<false, StorageType, R(*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X4>::ForwardType x4, typename internal::ParamTraits<X5>::ForwardType x5) { @@ -805,7 +1067,7 @@ struct Invoker3<StorageType, R(*)(X1, X2, X3, X4, X5)> { // Method: Arity 4 -> 2. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4> -struct Invoker3<StorageType, R(T::*)(X1, X2, X3, X4)> { +struct Invoker3<false, StorageType, R(T::*)(X1, X2, X3, X4)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X3>::ForwardType x3, typename internal::ParamTraits<X4>::ForwardType x4) { @@ -815,10 +1077,27 @@ struct Invoker3<StorageType, R(T::*)(X1, X2, X3, X4)> { } }; +// WeakPtr Method: Arity 4 -> 2. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4> +struct Invoker3<true, StorageType, void(T::*)(X1, X2, X3, X4)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4) { + StorageType* invoker = static_cast<StorageType*>(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 <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> -struct Invoker3<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { +struct Invoker3<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X4>::ForwardType x4, typename internal::ParamTraits<X5>::ForwardType x5, @@ -832,7 +1111,7 @@ struct Invoker3<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { // Method: Arity 5 -> 3. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker3<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { +struct Invoker3<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X3>::ForwardType x3, typename internal::ParamTraits<X4>::ForwardType x4, @@ -843,13 +1122,31 @@ struct Invoker3<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { } }; -template <typename StorageType, typename NormalizedSig> +// WeakPtr Method: Arity 5 -> 3. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4, typename X5> +struct Invoker3<true, StorageType, void(T::*)(X1, X2, X3, X4, X5)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X3>::ForwardType x3, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5) { + StorageType* invoker = static_cast<StorageType*>(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 <bool IsWeak, typename StorageType, typename NormalizedSig> struct Invoker4; // Function: Arity 4 -> 0. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4> -struct Invoker4<StorageType, R(*)(X1, X2, X3, X4)> { +struct Invoker4<false, StorageType, R(*)(X1, X2, X3, X4)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), @@ -860,7 +1157,7 @@ struct Invoker4<StorageType, R(*)(X1, X2, X3, X4)> { // Method: Arity 3 -> 0. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3> -struct Invoker4<StorageType, R(T::*)(X1, X2, X3)> { +struct Invoker4<false, StorageType, R(T::*)(X1, X2, X3)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), @@ -868,10 +1165,25 @@ struct Invoker4<StorageType, R(T::*)(X1, X2, X3)> { } }; +// WeakPtr Method: Arity 3 -> 0. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3> +struct Invoker4<true, StorageType, void(T::*)(X1, X2, X3)> { + static void DoInvoke(InvokerStorageBase* base) { + StorageType* invoker = static_cast<StorageType*>(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 <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker4<StorageType, R(*)(X1, X2, X3, X4, X5)> { +struct Invoker4<false, StorageType, R(*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X5>::ForwardType x5) { StorageType* invoker = static_cast<StorageType*>(base); @@ -883,7 +1195,7 @@ struct Invoker4<StorageType, R(*)(X1, X2, X3, X4, X5)> { // Method: Arity 4 -> 1. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4> -struct Invoker4<StorageType, R(T::*)(X1, X2, X3, X4)> { +struct Invoker4<false, StorageType, R(T::*)(X1, X2, X3, X4)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X4>::ForwardType x4) { StorageType* invoker = static_cast<StorageType*>(base); @@ -892,10 +1204,26 @@ struct Invoker4<StorageType, R(T::*)(X1, X2, X3, X4)> { } }; +// WeakPtr Method: Arity 4 -> 1. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4> +struct Invoker4<true, StorageType, void(T::*)(X1, X2, X3, X4)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X4>::ForwardType x4) { + StorageType* invoker = static_cast<StorageType*>(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 <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> -struct Invoker4<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { +struct Invoker4<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X5>::ForwardType x5, typename internal::ParamTraits<X6>::ForwardType x6) { @@ -908,7 +1236,7 @@ struct Invoker4<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { // Method: Arity 5 -> 2. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker4<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { +struct Invoker4<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X4>::ForwardType x4, typename internal::ParamTraits<X5>::ForwardType x5) { @@ -918,13 +1246,30 @@ struct Invoker4<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { } }; -template <typename StorageType, typename NormalizedSig> +// WeakPtr Method: Arity 5 -> 2. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4, typename X5> +struct Invoker4<true, StorageType, void(T::*)(X1, X2, X3, X4, X5)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X4>::ForwardType x4, + typename internal::ParamTraits<X5>::ForwardType x5) { + StorageType* invoker = static_cast<StorageType*>(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 <bool IsWeak, typename StorageType, typename NormalizedSig> struct Invoker5; // Function: Arity 5 -> 0. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker5<StorageType, R(*)(X1, X2, X3, X4, X5)> { +struct Invoker5<false, StorageType, R(*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), @@ -935,7 +1280,7 @@ struct Invoker5<StorageType, R(*)(X1, X2, X3, X4, X5)> { // Method: Arity 4 -> 0. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4> -struct Invoker5<StorageType, R(T::*)(X1, X2, X3, X4)> { +struct Invoker5<false, StorageType, R(T::*)(X1, X2, X3, X4)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), @@ -943,10 +1288,25 @@ struct Invoker5<StorageType, R(T::*)(X1, X2, X3, X4)> { } }; +// WeakPtr Method: Arity 4 -> 0. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4> +struct Invoker5<true, StorageType, void(T::*)(X1, X2, X3, X4)> { + static void DoInvoke(InvokerStorageBase* base) { + StorageType* invoker = static_cast<StorageType*>(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 <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> -struct Invoker5<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { +struct Invoker5<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X6>::ForwardType x6) { StorageType* invoker = static_cast<StorageType*>(base); @@ -958,7 +1318,7 @@ struct Invoker5<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { // Method: Arity 5 -> 1. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker5<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { +struct Invoker5<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base, typename internal::ParamTraits<X5>::ForwardType x5) { StorageType* invoker = static_cast<StorageType*>(base); @@ -967,13 +1327,29 @@ struct Invoker5<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { } }; -template <typename StorageType, typename NormalizedSig> +// WeakPtr Method: Arity 5 -> 1. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4, typename X5> +struct Invoker5<true, StorageType, void(T::*)(X1, X2, X3, X4, X5)> { + static void DoInvoke(InvokerStorageBase* base, + typename internal::ParamTraits<X5>::ForwardType x5) { + StorageType* invoker = static_cast<StorageType*>(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 <bool IsWeak, typename StorageType, typename NormalizedSig> struct Invoker6; // Function: Arity 6 -> 0. template <typename StorageType, typename R,typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> -struct Invoker6<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { +struct Invoker6<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), @@ -985,7 +1361,7 @@ struct Invoker6<StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { // Method: Arity 5 -> 0. template <typename StorageType, typename R, typename T, typename X1, typename X2, typename X3, typename X4, typename X5> -struct Invoker6<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { +struct Invoker6<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> { static R DoInvoke(InvokerStorageBase* base) { StorageType* invoker = static_cast<StorageType*>(base); return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), @@ -994,6 +1370,20 @@ struct Invoker6<StorageType, R(T::*)(X1, X2, X3, X4, X5)> { } }; +// WeakPtr Method: Arity 5 -> 0. +template <typename StorageType, typename T, typename X1, typename X2, + typename X3, typename X4, typename X5> +struct Invoker6<true, StorageType, void(T::*)(X1, X2, X3, X4, X5)> { + static void DoInvoke(InvokerStorageBase* base) { + StorageType* invoker = static_cast<StorageType*>(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<Sig> TargetTraits; - typedef Invoker0<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + typedef Invoker0<false, StorageType, + typename TargetTraits::NormalizedSig> Invoker; @@ -1033,8 +1425,14 @@ class InvokerStorage1 : public InvokerStorageBase { public: typedef InvokerStorage1 StorageType; typedef FunctionTraits<Sig> TargetTraits; - typedef Invoker1<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + typedef ParamTraits<P1> P1Traits; + typedef Invoker1<IsWeakMethod<IsMethod::value, P1>::value, StorageType, + typename TargetTraits::NormalizedSig> Invoker; + COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) || + is_void<typename TargetTraits::Return>::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<Sig> TargetTraits; - typedef Invoker2<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + typedef ParamTraits<P1> P1Traits; + typedef ParamTraits<P2> P2Traits; + typedef Invoker2<IsWeakMethod<IsMethod::value, P1>::value, StorageType, + typename TargetTraits::NormalizedSig> Invoker; + COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) || + is_void<typename TargetTraits::Return>::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<Sig> TargetTraits; - typedef Invoker3<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + typedef ParamTraits<P1> P1Traits; + typedef ParamTraits<P2> P2Traits; + typedef ParamTraits<P3> P3Traits; + typedef Invoker3<IsWeakMethod<IsMethod::value, P1>::value, StorageType, + typename TargetTraits::NormalizedSig> Invoker; + COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) || + is_void<typename TargetTraits::Return>::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<Sig> TargetTraits; - typedef Invoker4<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + typedef ParamTraits<P1> P1Traits; + typedef ParamTraits<P2> P2Traits; + typedef ParamTraits<P3> P3Traits; + typedef ParamTraits<P4> P4Traits; + typedef Invoker4<IsWeakMethod<IsMethod::value, P1>::value, StorageType, + typename TargetTraits::NormalizedSig> Invoker; + COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) || + is_void<typename TargetTraits::Return>::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<Sig> TargetTraits; - typedef Invoker5<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + typedef ParamTraits<P1> P1Traits; + typedef ParamTraits<P2> P2Traits; + typedef ParamTraits<P3> P3Traits; + typedef ParamTraits<P4> P4Traits; + typedef ParamTraits<P5> P5Traits; + typedef Invoker5<IsWeakMethod<IsMethod::value, P1>::value, StorageType, + typename TargetTraits::NormalizedSig> Invoker; + COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) || + is_void<typename TargetTraits::Return>::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<Sig> TargetTraits; - typedef Invoker6<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + typedef ParamTraits<P1> P1Traits; + typedef ParamTraits<P2> P2Traits; + typedef ParamTraits<P3> P3Traits; + typedef ParamTraits<P4> P4Traits; + typedef ParamTraits<P5> P5Traits; + typedef ParamTraits<P6> P6Traits; + typedef Invoker6<IsWeakMethod<IsMethod::value, P1>::value, StorageType, + typename TargetTraits::NormalizedSig> Invoker; + COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) || + is_void<typename TargetTraits::Return>::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 <bool IsMethod, typename T> +struct IsWeakMethod : public false_type {}; + +template <typename T> +struct IsWeakMethod<true, WeakPtr<T> > : public true_type {}; + // FunctionTraits<> // // The FunctionTraits<> template determines the type of function, and also @@ -83,6 +95,8 @@ struct FunctionTraits<R(*)($for ARG , [[X$(ARG)]])> { 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<R(T::*)($for ARG , [[X$(ARG)]])> { 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<R(T::*)($for ARG , [[X$(ARG)]]) const> { 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 <typename StorageType, typename NormalizedSig> +template <bool IsWeak, typename StorageType, typename NormalizedSig> struct Invoker$(BOUND); $range ARITY 0..MAX_ARITY @@ -179,7 +197,7 @@ $range M_UNBOUND_ARG (M_ARITY - UNBOUND + 1)..M_ARITY template <typename StorageType, typename R[[]] $if ARITY > 0 [[,]][[]] $for ARG , [[typename X$(ARG)]]> -struct Invoker$(BOUND)<StorageType, R(*)($for ARG , [[X$(ARG)]])> { +struct Invoker$(BOUND)<false, StorageType, R(*)($for ARG , [[X$(ARG)]])> { static R DoInvoke(InvokerStorageBase* base[[]] $if UNBOUND != 0 [[, ]][[]] $for UNBOUND_ARG , [[typename internal::ParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG)]]) { @@ -196,7 +214,7 @@ $if BOUND > 0 [[ // Method: Arity $(M_ARITY) -> $(UNBOUND). template <typename StorageType, typename R, typename T[[]] $if M_ARITY > 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]> -struct Invoker$(BOUND)<StorageType, R(T::*)($for M_ARG , [[X$(M_ARG)]])> { +struct Invoker$(BOUND)<false, StorageType, R(T::*)($for M_ARG , [[X$(M_ARG)]])> { static R DoInvoke(InvokerStorageBase* base[[]] $if UNBOUND > 0 [[, ]][[]] $for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::ForwardType x$(M_UNBOUND_ARG)]]) { @@ -208,13 +226,31 @@ $for M_UNBOUND_ARG , [[x$(M_UNBOUND_ARG)]]); } }; +// WeakPtr Method: Arity $(M_ARITY) -> $(UNBOUND). +template <typename StorageType, typename T[[]] +$if M_ARITY > 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]> +struct Invoker$(BOUND)<true, StorageType, void(T::*)($for M_ARG , [[X$(M_ARG)]])> { + static void DoInvoke(InvokerStorageBase* base[[]] +$if UNBOUND > 0 [[, ]][[]] +$for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::ForwardType x$(M_UNBOUND_ARG)]]) { + StorageType* invoker = static_cast<StorageType*>(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<Sig> TargetTraits; - typedef Invoker$(BOUND)<StorageType, typename TargetTraits::NormalizedSig> Invoker; typedef typename TargetTraits::IsMethod IsMethod; + typedef Sig Signature; + +$for BOUND_ARG [[ + typedef ParamTraits<P$(BOUND_ARG)> P$(BOUND_ARG)Traits; + +]] + +$if BOUND == 0 [[ + typedef Invoker$(BOUND)<false, StorageType, + typename TargetTraits::NormalizedSig> Invoker; +]] $else [[ + typedef Invoker$(BOUND)<IsWeakMethod<IsMethod::value, P1>::value, StorageType, + typename TargetTraits::NormalizedSig> Invoker; + COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) || + is_void<typename TargetTraits::Return>::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 <typename R> struct FunctionTraits<R(__stdcall *)()> { typedef R (*NormalizedSig)(); typedef false_type IsMethod; + + typedef R Return; }; // __fastcall Function: Arity 0. @@ -38,6 +40,8 @@ template <typename R> struct FunctionTraits<R(__fastcall *)()> { typedef R (*NormalizedSig)(); typedef false_type IsMethod; + + typedef R Return; }; // __stdcall Function: Arity 1. @@ -45,6 +49,9 @@ template <typename R, typename X1> struct FunctionTraits<R(__stdcall *)(X1)> { 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 <typename R, typename X1> struct FunctionTraits<R(__fastcall *)(X1)> { 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 <typename R, typename X1, typename X2> struct FunctionTraits<R(__stdcall *)(X1, X2)> { 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 <typename R, typename X1, typename X2> struct FunctionTraits<R(__fastcall *)(X1, X2)> { 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 <typename R, typename X1, typename X2, typename X3> struct FunctionTraits<R(__stdcall *)(X1, X2, X3)> { 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 <typename R, typename X1, typename X2, typename X3> struct FunctionTraits<R(__fastcall *)(X1, X2, X3)> { 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 <typename R, typename X1, typename X2, typename X3, typename X4> struct FunctionTraits<R(__stdcall *)(X1, X2, X3, X4)> { 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 <typename R, typename X1, typename X2, typename X3, typename X4> struct FunctionTraits<R(__fastcall *)(X1, X2, X3, X4)> { 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 <typename R, typename X1, typename X2, typename X3, typename X4, struct FunctionTraits<R(__stdcall *)(X1, X2, X3, X4, X5)> { 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 <typename R, typename X1, typename X2, typename X3, typename X4, struct FunctionTraits<R(__fastcall *)(X1, X2, X3, X4, X5)> { 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 <typename R, typename X1, typename X2, typename X3, typename X4, struct FunctionTraits<R(__stdcall *)(X1, X2, X3, X4, X5, X6)> { 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 <typename R, typename X1, typename X2, typename X3, typename X4, struct FunctionTraits<R(__fastcall *)(X1, X2, X3, X4, X5, X6)> { 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<R(__stdcall *)($for ARG , [[X$(ARG)]])> { 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<R(__fastcall *)($for ARG , [[X$(ARG)]])> { 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<NoRef> 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<NoRef> weak_factory(&no_ref_); + WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_); + + Callback<void(void)> method_cb = + Bind(&NoRef::VoidMethod0, weak_factory.GetWeakPtr()); + method_cb.Run(); + + Callback<void(void)> const_method_cb = + Bind(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr()); + const_method_cb.Run(); + + Callback<void(void)> const_method_const_ptr_cb = + Bind(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr()); + const_method_const_ptr_cb.Run(); + + Callback<int(int)> 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<void(void)> ref_count_as_raw_ptr = // Bind(&VoidPolymorphic1<HasRef*>, &for_raw_ptr); + // - WeakPtrs cannot be bound to methods with return types. + // HasRef for_raw_ptr; + // WeakPtrFactory<NoRef> weak_factory(&no_ref_); + // Callback<int(void)> 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<Ref> { 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<int(int)> func_cb = base::Bind(&Return5); -// LOG(INFO) << func_cb.Run(5); // Prints 5. +// base::Callback<int(void)> 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<Ref> { @@ -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 <class T> struct is_non_const_reference : false_type {}; template <class T> struct is_non_const_reference<T&> : true_type {}; template <class T> struct is_non_const_reference<const T&> : false_type {}; +template <class T> struct is_void : false_type {}; +template <> struct is_void<void> : true_type {}; + namespace internal { // Types YesType and NoType are guaranteed such that sizeof(YesType) < |