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 /base/bind_internal.h.pump | |
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
Diffstat (limited to 'base/bind_internal.h.pump')
-rw-r--r-- | base/bind_internal.h.pump | 63 |
1 files changed, 58 insertions, 5 deletions
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 [[ |