diff options
author | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-28 22:13:54 +0000 |
---|---|---|
committer | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-28 22:13:54 +0000 |
commit | fccef1559e02b001c69a0d35ad960e37dcbfd650 (patch) | |
tree | b3ddaa715bf24e5d44a134b7298f39e59b2c1f27 | |
parent | 485c5558393ab8fa34c580eed539a37d9d8f1450 (diff) | |
download | chromium_src-fccef1559e02b001c69a0d35ad960e37dcbfd650.zip chromium_src-fccef1559e02b001c69a0d35ad960e37dcbfd650.tar.gz chromium_src-fccef1559e02b001c69a0d35ad960e37dcbfd650.tar.bz2 |
Increase Bind/Callback Arity from 6 -> 7.
A few functions need this and the expected compile-speed impact is low. We should be careful when raising this number higher. If you're binding a function that has more parameters than this supports, consider refactoring your API to use a parameter struct or something.
Template equation: (n^2 + 26n) / 2
Template growth: 96 -> 116 types.
BUG=98542
TEST=try bots
Review URL: http://codereview.chromium.org/8728010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111788 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/bind.h | 77 | ||||
-rw-r--r-- | base/bind.h.pump | 20 | ||||
-rw-r--r-- | base/bind_internal.h | 545 | ||||
-rw-r--r-- | base/bind_internal.h.pump | 9 | ||||
-rw-r--r-- | base/bind_internal_win.h | 51 | ||||
-rw-r--r-- | base/bind_internal_win.h.pump | 3 | ||||
-rw-r--r-- | base/callback.h | 64 | ||||
-rw-r--r-- | base/callback.h.pump | 3 |
8 files changed, 751 insertions, 21 deletions
diff --git a/base/bind.h b/base/bind.h index 1637207..aa2cc6b 100644 --- a/base/bind.h +++ b/base/bind.h @@ -3,7 +3,6 @@ // DO NOT EDIT BY HAND!!! - // 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. @@ -410,6 +409,82 @@ Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4, internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6)); } +template <typename Functor, typename P1, typename P2, typename P3, typename P4, + typename P5, typename P6, typename P7> +internal::BindStateHolder< + internal::BindState< + typename internal::FunctorTraits<Functor>::RunnableType, + typename internal::FunctorTraits<Functor>::RunType, + void(typename internal::CallbackParamTraits<P1>::StorageType, + typename internal::CallbackParamTraits<P2>::StorageType, + typename internal::CallbackParamTraits<P3>::StorageType, + typename internal::CallbackParamTraits<P4>::StorageType, + typename internal::CallbackParamTraits<P5>::StorageType, + typename internal::CallbackParamTraits<P6>::StorageType, + typename internal::CallbackParamTraits<P7>::StorageType)> > +Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4, + const P5& p5, const P6& p6, const P7& p7) { + // Typedefs for how to store and run the functor. + typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType; + typedef typename internal::FunctorTraits<Functor>::RunType RunType; + + // Use RunnableType::RunType instead of RunType above because our + // checks should below for bound references need to know what the actual + // functor is going to interpret the argument as. + typedef internal::FunctionTraits<typename RunnableType::RunType> + BoundFunctorTraits; + + // Do not allow binding a non-const reference parameter. Non-const reference + // parameters are disallowed by the Google style guide. Also, binding a + // non-const reference parameter can make for subtle bugs because the + // invoked function will receive a reference to the stored copy of the + // argument and not the original. + COMPILE_ASSERT( + !(is_non_const_reference<typename BoundFunctorTraits::A1Type>::value || + is_non_const_reference<typename BoundFunctorTraits::A2Type>::value || + is_non_const_reference<typename BoundFunctorTraits::A3Type>::value || + is_non_const_reference<typename BoundFunctorTraits::A4Type>::value || + is_non_const_reference<typename BoundFunctorTraits::A5Type>::value || + is_non_const_reference<typename BoundFunctorTraits::A6Type>::value || + is_non_const_reference<typename BoundFunctorTraits::A7Type>::value ), + do_not_bind_functions_with_nonconst_ref); + + // For methods, we need to be careful for parameter 1. We do not require + // a scoped_refptr because BindState<> itself takes care of AddRef() for + // methods. We also disallow binding of an array as the method's target + // object. + COMPILE_ASSERT( + internal::HasIsMethodTag<RunnableType>::value || + !internal::NeedsScopedRefptrButGetsRawPtr<P1>::value, + p1_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value || + !is_array<P1>::value, + first_bound_argument_to_method_cannot_be_array); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P2>::value, + p2_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P3>::value, + p3_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P4>::value, + p4_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P5>::value, + p5_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P6>::value, + p6_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P7>::value, + p7_is_refcounted_type_and_needs_scoped_refptr); + + return internal::MakeBindStateHolder( + new internal::BindState<RunnableType, RunType, + void(typename internal::CallbackParamTraits<P1>::StorageType, + typename internal::CallbackParamTraits<P2>::StorageType, + typename internal::CallbackParamTraits<P3>::StorageType, + typename internal::CallbackParamTraits<P4>::StorageType, + typename internal::CallbackParamTraits<P5>::StorageType, + typename internal::CallbackParamTraits<P6>::StorageType, + typename internal::CallbackParamTraits<P7>::StorageType)>( + internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6, p7)); +} + } // namespace base #endif // BASE_BIND_H_ diff --git a/base/bind.h.pump b/base/bind.h.pump index 11b4667..9d4c5ee 100644 --- a/base/bind.h.pump +++ b/base/bind.h.pump @@ -5,7 +5,25 @@ $$ $$ http://code.google.com/p/googletest/wiki/PumpManual $$ -$var MAX_ARITY = 6 +$$ +$$ MAX_ARITY controls the number of arguments that Bind() supports. +$$ The amount of code, and more importantly, the number of template types +$$ generated by pump grows at O(MAX_ARITY^2). +$$ +$$ We tried going to 11 and found it imposed an extra 10 penalty on windows +$$ cycle times compared to our original baseline of 6. +$$ +$$ Currently 7 is chosen as a compromise between supporting a convenient +$$ number of arguments and keeping compile times low. At 7, we have 115 +$$ templates being generated by pump. +$$ +$$ Be careful when adjusting this number. If people find a need to bind +$$ a larger number of arguments, consider refactoring the function to use +$$ a param struct instead of raising the MAX_ARITY. +$$ +$$ See http://crbug.com/98542 for more context. +$$ +$var MAX_ARITY = 7 // Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be diff --git a/base/bind_internal.h b/base/bind_internal.h index 6c76d80..ccd7ab2 100644 --- a/base/bind_internal.h +++ b/base/bind_internal.h @@ -3,13 +3,6 @@ // DO NOT EDIT BY HAND!!! - -// TODO(ajwong): If you create an fully unbound method, is there a way to -// enforce the first argument must be refcounted? Or do we just say -// "oh well"? -// -// Do we want to allow creating a fully unbound method?? - // 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. @@ -552,6 +545,83 @@ class RunnableAdapter<R(T::*)(A1, A2, A3, A4, A5, A6) const> { R (T::*method_)(A1, A2, A3, A4, A5, A6) const; }; +// Function: Arity 7. +template <typename R, typename A1, typename A2, typename A3, typename A4, + typename A5, typename A6, typename A7> +class RunnableAdapter<R(*)(A1, A2, A3, A4, A5, A6, A7)> { + public: + typedef R (RunType)(A1, A2, A3, A4, A5, A6, A7); + + explicit RunnableAdapter(R(*function)(A1, A2, A3, A4, A5, A6, A7)) + : function_(function) { + } + + R Run(typename CallbackParamTraits<A1>::ForwardType a1, + typename CallbackParamTraits<A2>::ForwardType a2, + typename CallbackParamTraits<A3>::ForwardType a3, + typename CallbackParamTraits<A4>::ForwardType a4, + typename CallbackParamTraits<A5>::ForwardType a5, + typename CallbackParamTraits<A6>::ForwardType a6, + typename CallbackParamTraits<A7>::ForwardType a7) { + return function_(a1, a2, a3, a4, a5, a6, a7); + } + + private: + R (*function_)(A1, A2, A3, A4, A5, A6, A7); +}; + +// Method: Arity 7. +template <typename R, typename T, typename A1, typename A2, typename A3, + typename A4, typename A5, typename A6, typename A7> +class RunnableAdapter<R(T::*)(A1, A2, A3, A4, A5, A6, A7)> { + public: + typedef R (RunType)(T*, A1, A2, A3, A4, A5, A6, A7); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5, A6, A7)) + : method_(method) { + } + + R Run(T* object, typename CallbackParamTraits<A1>::ForwardType a1, + typename CallbackParamTraits<A2>::ForwardType a2, + typename CallbackParamTraits<A3>::ForwardType a3, + typename CallbackParamTraits<A4>::ForwardType a4, + typename CallbackParamTraits<A5>::ForwardType a5, + typename CallbackParamTraits<A6>::ForwardType a6, + typename CallbackParamTraits<A7>::ForwardType a7) { + return (object->*method_)(a1, a2, a3, a4, a5, a6, a7); + } + + private: + R (T::*method_)(A1, A2, A3, A4, A5, A6, A7); +}; + +// Const Method: Arity 7. +template <typename R, typename T, typename A1, typename A2, typename A3, + typename A4, typename A5, typename A6, typename A7> +class RunnableAdapter<R(T::*)(A1, A2, A3, A4, A5, A6, A7) const> { + public: + typedef R (RunType)(const T*, A1, A2, A3, A4, A5, A6, A7); + typedef true_type IsMethod; + + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5, A6, A7) const) + : method_(method) { + } + + R Run(const T* object, typename CallbackParamTraits<A1>::ForwardType a1, + typename CallbackParamTraits<A2>::ForwardType a2, + typename CallbackParamTraits<A3>::ForwardType a3, + typename CallbackParamTraits<A4>::ForwardType a4, + typename CallbackParamTraits<A5>::ForwardType a5, + typename CallbackParamTraits<A6>::ForwardType a6, + typename CallbackParamTraits<A7>::ForwardType a7) { + return (object->*method_)(a1, a2, a3, a4, a5, a6, a7); + } + + private: + R (T::*method_)(A1, A2, A3, A4, A5, A6, A7) const; +}; + // FunctionTraits<> // @@ -617,6 +687,19 @@ struct FunctionTraits<R(A1, A2, A3, A4, A5, A6)> { typedef A6 A6Type; }; +template <typename R, typename A1, typename A2, typename A3, typename A4, + typename A5, typename A6, typename A7> +struct FunctionTraits<R(A1, A2, A3, A4, A5, A6, A7)> { + typedef R ReturnType; + typedef A1 A1Type; + typedef A2 A2Type; + typedef A3 A3Type; + typedef A4 A4Type; + typedef A5 A5Type; + typedef A6 A6Type; + typedef A7 A7Type; +}; + // ForceVoidReturn<> // @@ -661,6 +744,12 @@ struct ForceVoidReturn<R(A1, A2, A3, A4, A5, A6)> { typedef void(RunType)(A1, A2, A3, A4, A5, A6); }; +template <typename R, typename A1, typename A2, typename A3, typename A4, + typename A5, typename A6, typename A7> +struct ForceVoidReturn<R(A1, A2, A3, A4, A5, A6, A7)> { + typedef void(RunType)(A1, A2, A3, A4, A5, A6, A7); +}; + // FunctorTraits<> // @@ -924,6 +1013,40 @@ struct InvokeHelper<true, void, Runnable, } }; +template <typename ReturnType, typename Runnable,typename A1, typename A2, + typename A3, typename A4, typename A5, typename A6, typename A7> +struct InvokeHelper<false, ReturnType, Runnable, + void(A1, A2, A3, A4, A5, A6, A7)> { + static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, + A5 a5, A6 a6, A7 a7) { + return runnable.Run(a1, a2, a3, a4, a5, a6, a7); + } +}; + +template <typename Runnable,typename A1, typename A2, typename A3, typename A4, + typename A5, typename A6, typename A7> +struct InvokeHelper<false, void, Runnable, + void(A1, A2, A3, A4, A5, A6, A7)> { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, + A6 a6, A7 a7) { + runnable.Run(a1, a2, a3, a4, a5, a6, a7); + } +}; + +template <typename Runnable, typename A1, typename A2, typename A3, + typename A4, typename A5, typename A6, typename A7> +struct InvokeHelper<true, void, Runnable, + void(A1, A2, A3, A4, A5, A6, A7)> { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, + A6 a6, A7 a7) { + if (!a1.get()) { + return; + } + + runnable.Run(a1, a2, a3, a4, a5, a6, a7); + } +}; + #if !defined(_MSC_VER) template <typename ReturnType, typename Runnable, typename ArgsType> @@ -1918,6 +2041,370 @@ struct Invoker<6, StorageType, R(X1, X2, X3, X4, X5, X6)> { } }; +// Arity 7 -> 7. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4, typename X5, typename X6, typename X7> +struct Invoker<0, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X1>::ForwardType, + typename CallbackParamTraits<X2>::ForwardType, + typename CallbackParamTraits<X3>::ForwardType, + typename CallbackParamTraits<X4>::ForwardType, + typename CallbackParamTraits<X5>::ForwardType, + typename CallbackParamTraits<X6>::ForwardType, + typename CallbackParamTraits<X7>::ForwardType); + + typedef R(UnboundRunType)(X1, X2, X3, X4, X5, X6, X7); + + static R Run(BindStateBase* base, + typename CallbackParamTraits<X1>::ForwardType x1, + typename CallbackParamTraits<X2>::ForwardType x2, + typename CallbackParamTraits<X3>::ForwardType x3, + typename CallbackParamTraits<X4>::ForwardType x4, + typename CallbackParamTraits<X5>::ForwardType x5, + typename CallbackParamTraits<X6>::ForwardType x6, + typename CallbackParamTraits<X7>::ForwardType x7) { + StorageType* storage = static_cast<StorageType*>(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + + return InvokeHelper<StorageType::IsWeakCall::value, R, + typename StorageType::RunnableType, + void(typename CallbackParamTraits<X1>::ForwardType x1, + typename CallbackParamTraits<X2>::ForwardType x2, + typename CallbackParamTraits<X3>::ForwardType x3, + typename CallbackParamTraits<X4>::ForwardType x4, + typename CallbackParamTraits<X5>::ForwardType x5, + typename CallbackParamTraits<X6>::ForwardType x6, + typename CallbackParamTraits<X7>::ForwardType x7)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6, x7); + } +}; + +// Arity 7 -> 6. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4, typename X5, typename X6, typename X7> +struct Invoker<1, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X2>::ForwardType, + typename CallbackParamTraits<X3>::ForwardType, + typename CallbackParamTraits<X4>::ForwardType, + typename CallbackParamTraits<X5>::ForwardType, + typename CallbackParamTraits<X6>::ForwardType, + typename CallbackParamTraits<X7>::ForwardType); + + typedef R(UnboundRunType)(X2, X3, X4, X5, X6, X7); + + static R Run(BindStateBase* base, + typename CallbackParamTraits<X2>::ForwardType x2, + typename CallbackParamTraits<X3>::ForwardType x3, + typename CallbackParamTraits<X4>::ForwardType x4, + typename CallbackParamTraits<X5>::ForwardType x5, + typename CallbackParamTraits<X6>::ForwardType x6, + typename CallbackParamTraits<X7>::ForwardType x7) { + StorageType* storage = static_cast<StorageType*>(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + return InvokeHelper<StorageType::IsWeakCall::value, R, + typename StorageType::RunnableType, + void(typename Bound1UnwrapTraits::ForwardType, + typename CallbackParamTraits<X2>::ForwardType x2, + typename CallbackParamTraits<X3>::ForwardType x3, + typename CallbackParamTraits<X4>::ForwardType x4, + typename CallbackParamTraits<X5>::ForwardType x5, + typename CallbackParamTraits<X6>::ForwardType x6, + typename CallbackParamTraits<X7>::ForwardType x7)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6, x7); + } +}; + +// Arity 7 -> 5. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4, typename X5, typename X6, typename X7> +struct Invoker<2, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X3>::ForwardType, + typename CallbackParamTraits<X4>::ForwardType, + typename CallbackParamTraits<X5>::ForwardType, + typename CallbackParamTraits<X6>::ForwardType, + typename CallbackParamTraits<X7>::ForwardType); + + typedef R(UnboundRunType)(X3, X4, X5, X6, X7); + + static R Run(BindStateBase* base, + typename CallbackParamTraits<X3>::ForwardType x3, + typename CallbackParamTraits<X4>::ForwardType x4, + typename CallbackParamTraits<X5>::ForwardType x5, + typename CallbackParamTraits<X6>::ForwardType x6, + typename CallbackParamTraits<X7>::ForwardType x7) { + StorageType* storage = static_cast<StorageType*>(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + return InvokeHelper<StorageType::IsWeakCall::value, R, + typename StorageType::RunnableType, + void(typename Bound1UnwrapTraits::ForwardType, + typename Bound2UnwrapTraits::ForwardType, + typename CallbackParamTraits<X3>::ForwardType x3, + typename CallbackParamTraits<X4>::ForwardType x4, + typename CallbackParamTraits<X5>::ForwardType x5, + typename CallbackParamTraits<X6>::ForwardType x6, + typename CallbackParamTraits<X7>::ForwardType x7)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6, x7); + } +}; + +// Arity 7 -> 4. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4, typename X5, typename X6, typename X7> +struct Invoker<3, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X4>::ForwardType, + typename CallbackParamTraits<X5>::ForwardType, + typename CallbackParamTraits<X6>::ForwardType, + typename CallbackParamTraits<X7>::ForwardType); + + typedef R(UnboundRunType)(X4, X5, X6, X7); + + static R Run(BindStateBase* base, + typename CallbackParamTraits<X4>::ForwardType x4, + typename CallbackParamTraits<X5>::ForwardType x5, + typename CallbackParamTraits<X6>::ForwardType x6, + typename CallbackParamTraits<X7>::ForwardType x7) { + StorageType* storage = static_cast<StorageType*>(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + return InvokeHelper<StorageType::IsWeakCall::value, R, + typename StorageType::RunnableType, + void(typename Bound1UnwrapTraits::ForwardType, + typename Bound2UnwrapTraits::ForwardType, + typename Bound3UnwrapTraits::ForwardType, + typename CallbackParamTraits<X4>::ForwardType x4, + typename CallbackParamTraits<X5>::ForwardType x5, + typename CallbackParamTraits<X6>::ForwardType x6, + typename CallbackParamTraits<X7>::ForwardType x7)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6, x7); + } +}; + +// Arity 7 -> 3. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4, typename X5, typename X6, typename X7> +struct Invoker<4, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X5>::ForwardType, + typename CallbackParamTraits<X6>::ForwardType, + typename CallbackParamTraits<X7>::ForwardType); + + typedef R(UnboundRunType)(X5, X6, X7); + + static R Run(BindStateBase* base, + typename CallbackParamTraits<X5>::ForwardType x5, + typename CallbackParamTraits<X6>::ForwardType x6, + typename CallbackParamTraits<X7>::ForwardType x7) { + StorageType* storage = static_cast<StorageType*>(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + return InvokeHelper<StorageType::IsWeakCall::value, R, + typename StorageType::RunnableType, + void(typename Bound1UnwrapTraits::ForwardType, + typename Bound2UnwrapTraits::ForwardType, + typename Bound3UnwrapTraits::ForwardType, + typename Bound4UnwrapTraits::ForwardType, + typename CallbackParamTraits<X5>::ForwardType x5, + typename CallbackParamTraits<X6>::ForwardType x6, + typename CallbackParamTraits<X7>::ForwardType x7)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6, x7); + } +}; + +// Arity 7 -> 2. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4, typename X5, typename X6, typename X7> +struct Invoker<5, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X6>::ForwardType, + typename CallbackParamTraits<X7>::ForwardType); + + typedef R(UnboundRunType)(X6, X7); + + static R Run(BindStateBase* base, + typename CallbackParamTraits<X6>::ForwardType x6, + typename CallbackParamTraits<X7>::ForwardType x7) { + StorageType* storage = static_cast<StorageType*>(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + typename Bound5UnwrapTraits::ForwardType x5 = + Bound5UnwrapTraits::Unwrap(storage->p5_); + return InvokeHelper<StorageType::IsWeakCall::value, R, + typename StorageType::RunnableType, + void(typename Bound1UnwrapTraits::ForwardType, + typename Bound2UnwrapTraits::ForwardType, + typename Bound3UnwrapTraits::ForwardType, + typename Bound4UnwrapTraits::ForwardType, + typename Bound5UnwrapTraits::ForwardType, + typename CallbackParamTraits<X6>::ForwardType x6, + typename CallbackParamTraits<X7>::ForwardType x7)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6, x7); + } +}; + +// Arity 7 -> 1. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4, typename X5, typename X6, typename X7> +struct Invoker<6, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X7>::ForwardType); + + typedef R(UnboundRunType)(X7); + + static R Run(BindStateBase* base, + typename CallbackParamTraits<X7>::ForwardType x7) { + StorageType* storage = static_cast<StorageType*>(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits; + typedef typename StorageType::Bound6UnwrapTraits Bound6UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + typename Bound5UnwrapTraits::ForwardType x5 = + Bound5UnwrapTraits::Unwrap(storage->p5_); + typename Bound6UnwrapTraits::ForwardType x6 = + Bound6UnwrapTraits::Unwrap(storage->p6_); + return InvokeHelper<StorageType::IsWeakCall::value, R, + typename StorageType::RunnableType, + void(typename Bound1UnwrapTraits::ForwardType, + typename Bound2UnwrapTraits::ForwardType, + typename Bound3UnwrapTraits::ForwardType, + typename Bound4UnwrapTraits::ForwardType, + typename Bound5UnwrapTraits::ForwardType, + typename Bound6UnwrapTraits::ForwardType, + typename CallbackParamTraits<X7>::ForwardType x7)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6, x7); + } +}; + +// Arity 7 -> 0. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4, typename X5, typename X6, typename X7> +struct Invoker<7, StorageType, R(X1, X2, X3, X4, X5, X6, X7)> { + typedef R(RunType)(BindStateBase*); + + typedef R(UnboundRunType)(); + + static R Run(BindStateBase* base) { + StorageType* storage = static_cast<StorageType*>(base); + + // Local references to make debugger stepping easier. If in a debugger, + // you really want to warp ahead and step through the + // InvokeHelper<>::MakeItSo() call below. + typedef typename StorageType::Bound1UnwrapTraits Bound1UnwrapTraits; + typedef typename StorageType::Bound2UnwrapTraits Bound2UnwrapTraits; + typedef typename StorageType::Bound3UnwrapTraits Bound3UnwrapTraits; + typedef typename StorageType::Bound4UnwrapTraits Bound4UnwrapTraits; + typedef typename StorageType::Bound5UnwrapTraits Bound5UnwrapTraits; + typedef typename StorageType::Bound6UnwrapTraits Bound6UnwrapTraits; + typedef typename StorageType::Bound7UnwrapTraits Bound7UnwrapTraits; + + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + typename Bound2UnwrapTraits::ForwardType x2 = + Bound2UnwrapTraits::Unwrap(storage->p2_); + typename Bound3UnwrapTraits::ForwardType x3 = + Bound3UnwrapTraits::Unwrap(storage->p3_); + typename Bound4UnwrapTraits::ForwardType x4 = + Bound4UnwrapTraits::Unwrap(storage->p4_); + typename Bound5UnwrapTraits::ForwardType x5 = + Bound5UnwrapTraits::Unwrap(storage->p5_); + typename Bound6UnwrapTraits::ForwardType x6 = + Bound6UnwrapTraits::Unwrap(storage->p6_); + typename Bound7UnwrapTraits::ForwardType x7 = + Bound7UnwrapTraits::Unwrap(storage->p7_); + return InvokeHelper<StorageType::IsWeakCall::value, R, + typename StorageType::RunnableType, + void(typename Bound1UnwrapTraits::ForwardType, + typename Bound2UnwrapTraits::ForwardType, + typename Bound3UnwrapTraits::ForwardType, + typename Bound4UnwrapTraits::ForwardType, + typename Bound5UnwrapTraits::ForwardType, + typename Bound6UnwrapTraits::ForwardType, + typename Bound7UnwrapTraits::ForwardType)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6, x7); + } +}; + // BindState<> // @@ -2142,6 +2629,50 @@ struct BindState<Runnable, RunType, void(P1, P2, P3, P4, P5, P6 p6_; }; +template <typename Runnable, typename RunType, typename P1, typename P2, + typename P3, typename P4, typename P5, typename P6, typename P7> +struct BindState<Runnable, RunType, void(P1, P2, P3, P4, P5, P6, + P7)> : public BindStateBase { + typedef Runnable RunnableType; + typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall; + typedef Invoker<7, BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + + // Convenience typedefs for bound argument types. + typedef UnwrapTraits<P1> Bound1UnwrapTraits; + typedef UnwrapTraits<P2> Bound2UnwrapTraits; + typedef UnwrapTraits<P3> Bound3UnwrapTraits; + typedef UnwrapTraits<P4> Bound4UnwrapTraits; + typedef UnwrapTraits<P5> Bound5UnwrapTraits; + typedef UnwrapTraits<P6> Bound6UnwrapTraits; + typedef UnwrapTraits<P7> Bound7UnwrapTraits; + + BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3, + const P4& p4, const P5& p5, const P6& p6, const P7& p7) + : runnable_(runnable), + p1_(p1), + p2_(p2), + p3_(p3), + p4_(p4), + p5_(p5), + p6_(p6), + p7_(p7) { + MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_); + } + + virtual ~BindState() { MaybeRefcount<HasIsMethodTag<Runnable>::value, + P1>::Release(p1_); } + + RunnableType runnable_; + P1 p1_; + P2 p2_; + P3 p3_; + P4 p4_; + P5 p5_; + P6 p6_; + P7 p7_; +}; + } // namespace internal } // namespace base diff --git a/base/bind_internal.h.pump b/base/bind_internal.h.pump index 1192974..53dcbd3 100644 --- a/base/bind_internal.h.pump +++ b/base/bind_internal.h.pump @@ -5,13 +5,8 @@ $$ $$ http://code.google.com/p/googletest/wiki/PumpManual $$ -// TODO(ajwong): If you create an fully unbound method, is there a way to -// enforce the first argument must be refcounted? Or do we just say -// "oh well"? -// -// Do we want to allow creating a fully unbound method?? - -$var MAX_ARITY = 6 +$$ See comment for MAX_ARITY in base/bind.h.pump. +$var MAX_ARITY = 7 $range ARITY 0..MAX_ARITY // Copyright (c) 2011 The Chromium Authors. All rights reserved. diff --git a/base/bind_internal_win.h b/base/bind_internal_win.h index 17d3aa3..b50361b 100644 --- a/base/bind_internal_win.h +++ b/base/bind_internal_win.h @@ -3,7 +3,6 @@ // DO NOT EDIT BY HAND!!! - // 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. @@ -312,6 +311,56 @@ class RunnableAdapter<R(__fastcall *)(A1, A2, A3, A4, A5, A6)> { R (__fastcall *function_)(A1, A2, A3, A4, A5, A6); }; +// __stdcall Function: Arity 7. +template <typename R, typename A1, typename A2, typename A3, typename A4, + typename A5, typename A6, typename A7> +class RunnableAdapter<R(__stdcall *)(A1, A2, A3, A4, A5, A6, A7)> { + public: + typedef R (RunType)(A1, A2, A3, A4, A5, A6, A7); + + explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3, A4, A5, A6, A7)) + : function_(function) { + } + + R Run(typename CallbackParamTraits<A1>::ForwardType a1, + typename CallbackParamTraits<A2>::ForwardType a2, + typename CallbackParamTraits<A3>::ForwardType a3, + typename CallbackParamTraits<A4>::ForwardType a4, + typename CallbackParamTraits<A5>::ForwardType a5, + typename CallbackParamTraits<A6>::ForwardType a6, + typename CallbackParamTraits<A7>::ForwardType a7) { + return function_(a1, a2, a3, a4, a5, a6, a7); + } + + private: + R (__stdcall *function_)(A1, A2, A3, A4, A5, A6, A7); +}; + +// __fastcall Function: Arity 7. +template <typename R, typename A1, typename A2, typename A3, typename A4, + typename A5, typename A6, typename A7> +class RunnableAdapter<R(__fastcall *)(A1, A2, A3, A4, A5, A6, A7)> { + public: + typedef R (RunType)(A1, A2, A3, A4, A5, A6, A7); + + explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3, A4, A5, A6, A7)) + : function_(function) { + } + + R Run(typename CallbackParamTraits<A1>::ForwardType a1, + typename CallbackParamTraits<A2>::ForwardType a2, + typename CallbackParamTraits<A3>::ForwardType a3, + typename CallbackParamTraits<A4>::ForwardType a4, + typename CallbackParamTraits<A5>::ForwardType a5, + typename CallbackParamTraits<A6>::ForwardType a6, + typename CallbackParamTraits<A7>::ForwardType a7) { + return function_(a1, a2, a3, a4, a5, a6, a7); + } + + private: + R (__fastcall *function_)(A1, A2, A3, A4, A5, A6, A7); +}; + } // namespace internal } // namespace base diff --git a/base/bind_internal_win.h.pump b/base/bind_internal_win.h.pump index 1d3b6b4..a557a29 100644 --- a/base/bind_internal_win.h.pump +++ b/base/bind_internal_win.h.pump @@ -5,7 +5,8 @@ $$ $$ http://code.google.com/p/googletest/wiki/PumpManual $$ -$var MAX_ARITY = 6 +$$ See comment for MAX_ARITY in base/bind.h.pump. +$var MAX_ARITY = 7 // Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be diff --git a/base/callback.h b/base/callback.h index 6844cc5..16e3ee6 100644 --- a/base/callback.h +++ b/base/callback.h @@ -3,7 +3,6 @@ // DO NOT EDIT BY HAND!!! - // 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. @@ -227,7 +226,7 @@ namespace base { // compiler that the template only has 1 type parameter which is the function // signature that the Callback is representing. // -// After this, create template specializations for 0-6 parameters. Note that +// After this, create template specializations for 0-7 parameters. Note that // even though the template typelist grows, the specialization still // only has one type: the function signature. template <typename Sig> @@ -573,6 +572,67 @@ class Callback<R(A1, A2, A3, A4, A5, A6)> : public internal::CallbackBase { }; +template <typename R, typename A1, typename A2, typename A3, typename A4, + typename A5, typename A6, typename A7> +class Callback<R(A1, A2, A3, A4, A5, A6, A7)> : public internal::CallbackBase { + public: + typedef R(RunType)(A1, A2, A3, A4, A5, A6, A7); + + Callback() : CallbackBase(NULL, NULL) { } + + // We pass BindStateHolder by const ref to avoid incurring an + // unnecessary AddRef/Unref pair even though we will modify the object. + // We cannot use a normal reference because the compiler will warn + // since this is often used on a return value, which is a temporary. + // + // Note that this constructor CANNOT be explicit, and that Bind() CANNOT + // return the exact Callback<> type. See base/bind.h for details. + template <typename T> + Callback(const internal::BindStateHolder<T>& bind_state_holder) + : CallbackBase(NULL, &bind_state_holder.bind_state_) { + // Force the assignment to a location variable of PolymorphicInvoke + // so the compiler will typecheck that the passed in Run() method has + // the correct type. + PolymorphicInvoke invoke_func = &T::InvokerType::Run; + polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func); + } + + bool Equals(const Callback& other) const { + return CallbackBase::Equals(other); + } + + R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1, + typename internal::CallbackParamTraits<A2>::ForwardType a2, + typename internal::CallbackParamTraits<A3>::ForwardType a3, + typename internal::CallbackParamTraits<A4>::ForwardType a4, + typename internal::CallbackParamTraits<A5>::ForwardType a5, + typename internal::CallbackParamTraits<A6>::ForwardType a6, + typename internal::CallbackParamTraits<A7>::ForwardType a7) const { + PolymorphicInvoke f = + reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); + + return f(bind_state_.get(), a1, + a2, + a3, + a4, + a5, + a6, + a7); + } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*, + typename internal::CallbackParamTraits<A1>::ForwardType, + typename internal::CallbackParamTraits<A2>::ForwardType, + typename internal::CallbackParamTraits<A3>::ForwardType, + typename internal::CallbackParamTraits<A4>::ForwardType, + typename internal::CallbackParamTraits<A5>::ForwardType, + typename internal::CallbackParamTraits<A6>::ForwardType, + typename internal::CallbackParamTraits<A7>::ForwardType); + +}; + // Syntactic sugar to make Callbacks<void(void)> easier to declare since it // will be used in a lot of APIs with delayed execution. diff --git a/base/callback.h.pump b/base/callback.h.pump index eee3371..aa43ad5 100644 --- a/base/callback.h.pump +++ b/base/callback.h.pump @@ -5,7 +5,8 @@ $$ $$ http://code.google.com/p/googletest/wiki/PumpManual $$ -$var MAX_ARITY = 6 +$$ See comment for MAX_ARITY in base/bind.h.pump. +$var MAX_ARITY = 7 // Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be |