diff options
author | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-21 19:23:44 +0000 |
---|---|---|
committer | ajwong@chromium.org <ajwong@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-21 19:23:44 +0000 |
commit | 7296f2763bd40e560466f09836c7208c42d90f94 (patch) | |
tree | 142a03c36f75f42738206355a029707ad88cdffc | |
parent | 1fbbf963079bc977ea041b7e50ddf4666f6fec38 (diff) | |
download | chromium_src-7296f2763bd40e560466f09836c7208c42d90f94.zip chromium_src-7296f2763bd40e560466f09836c7208c42d90f94.tar.gz chromium_src-7296f2763bd40e560466f09836c7208c42d90f94.tar.bz2 |
Callback API Change: Reimplement Bind(); support IgnoreResult, full currying, and use less types.
The main API change IgnoreResult() and fully currying. See unittest for what the new API looks like. The rest of the changes are done to support that.
Previously, IgnoreReturn could not be used with WeakPtr<> Bind()s as it was applied after the fact to the Callback object. Now, IgnoreResult() wraps the function like Unretained().
As an incidental benefit, the new implementation gave us fully currying for free.
Also, the new implementation scales better when supporting higher arities of functions. The new type growth is:
(n^2 + 20n) / 2
as opposed to
(3n^2 + 17n) / 2
where n == arity.
For n = 6 and n=10, the new implementation has 81 and 155 templates respectively.
The old implementation had 105 and 235 templates respectively.
BUG=35233,98919,98542
TEST=existing unittests
Review URL: http://codereview.chromium.org/8483003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@110975 0039d316-1c4b-4281-b951-d872f2087c98
33 files changed, 3286 insertions, 2702 deletions
diff --git a/base/at_exit_unittest.cc b/base/at_exit_unittest.cc index 89fc9d0..cda7340 100644 --- a/base/at_exit_unittest.cc +++ b/base/at_exit_unittest.cc @@ -81,7 +81,7 @@ TEST_F(AtExitTest, Param) { TEST_F(AtExitTest, Task) { ZeroTestCounters(); - base::AtExitManager::RegisterTask(base::Bind(ExpectParamIsCounter, + base::AtExitManager::RegisterTask(base::Bind(&ExpectParamIsCounter, &g_test_counter_1)); base::AtExitManager::ProcessCallbacksNow(); } diff --git a/base/bind.h b/base/bind.h index f023308e..1637207 100644 --- a/base/bind.h +++ b/base/bind.h @@ -15,7 +15,10 @@ #include "base/bind_internal.h" #include "base/callback_internal.h" -// See base/callback.h for how to use these functions. +// See base/callback.h for how to use these functions. If reading the +// implementation, before proceeding further, you should read the top +// comment of base/bind_internal.h for a definition of common terms and +// concepts. // // IMPLEMENTATION NOTE // Though Bind()'s result is meant to be stored in a Callback<> type, it @@ -28,116 +31,383 @@ // Each unique combination of (arity, function_type, num_prebound) where // function_type is one of {function, method, const_method} would require // one specialization. We eventually have to do a similar number of -// specializations anyways in the implementation (see the FunctionTraitsN, +// specializations anyways in the implementation (see the Invoker<>, // classes). However, it is avoidable in Bind if we return the result // via an indirection like we do below. +// +// TODO(ajwong): We might be able to avoid this now, but need to test. +// +// It is possible to move most of the COMPILE_ASSERT asserts into BindState<>, +// but it feels a little nicer to have the asserts here so people do not +// need to crack open bind_internal.h. On the other hand, it makes Bind() +// harder to read. namespace base { -template <typename Sig> -internal::InvokerStorageHolder<internal::InvokerStorage0<Sig> > -Bind(Sig f) { - return internal::MakeInvokerStorageHolder( - new internal::InvokerStorage0<Sig>(f)); -} +template <typename Functor> +internal::BindStateHolder< + internal::BindState< + typename internal::FunctorTraits<Functor>::RunnableType, + typename internal::FunctorTraits<Functor>::RunType, + void()> > +Bind(Functor functor) { + // Typedefs for how to store and run the functor. + typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType; + typedef typename internal::FunctorTraits<Functor>::RunType RunType; -template <typename Sig, typename P1> -internal::InvokerStorageHolder<internal::InvokerStorage1<Sig,P1> > -Bind(Sig f, const P1& p1) { - return internal::MakeInvokerStorageHolder( - new internal::InvokerStorage1<Sig, P1>( - f, p1)); -} + // 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; -template <typename Sig, typename P1, typename P2> -internal::InvokerStorageHolder<internal::InvokerStorage2<Sig,P1, P2> > -Bind(Sig f, const P1& p1, const P2& p2) { - return internal::MakeInvokerStorageHolder( - new internal::InvokerStorage2<Sig, P1, P2>( - f, p1, p2)); -} -template <typename Sig, typename P1, typename P2, typename P3> -internal::InvokerStorageHolder<internal::InvokerStorage3<Sig,P1, P2, P3> > -Bind(Sig f, const P1& p1, const P2& p2, const P3& p3) { - return internal::MakeInvokerStorageHolder( - new internal::InvokerStorage3<Sig, P1, P2, P3>( - f, p1, p2, p3)); + return internal::MakeBindStateHolder( + new internal::BindState<RunnableType, RunType, void()>( + internal::MakeRunnable(functor))); } -template <typename Sig, typename P1, typename P2, typename P3, typename P4> -internal::InvokerStorageHolder<internal::InvokerStorage4<Sig,P1, P2, P3, P4> > -Bind(Sig f, const P1& p1, const P2& p2, const P3& p3, const P4& p4) { - return internal::MakeInvokerStorageHolder( - new internal::InvokerStorage4<Sig, P1, P2, P3, P4>( - f, p1, p2, p3, p4)); -} +template <typename Functor, typename P1> +internal::BindStateHolder< + internal::BindState< + typename internal::FunctorTraits<Functor>::RunnableType, + typename internal::FunctorTraits<Functor>::RunType, + void(typename internal::CallbackParamTraits<P1>::StorageType)> > +Bind(Functor functor, const P1& p1) { + // Typedefs for how to store and run the functor. + typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType; + typedef typename internal::FunctorTraits<Functor>::RunType RunType; -template <typename Sig, typename P1, typename P2, typename P3, typename P4, - typename P5> -internal::InvokerStorageHolder<internal::InvokerStorage5<Sig,P1, P2, P3, P4, - P5> > -Bind(Sig f, const P1& p1, const P2& p2, const P3& p3, const P4& p4, - const P5& p5) { - return internal::MakeInvokerStorageHolder( - new internal::InvokerStorage5<Sig, P1, P2, P3, P4, P5>( - f, p1, p2, p3, p4, p5)); -} + // 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; -template <typename Sig, typename P1, typename P2, typename P3, typename P4, - typename P5, typename P6> -internal::InvokerStorageHolder<internal::InvokerStorage6<Sig,P1, P2, P3, P4, - P5, P6> > -Bind(Sig f, const P1& p1, const P2& p2, const P3& p3, const P4& p4, - const P5& p5, const P6& p6) { - return internal::MakeInvokerStorageHolder( - new internal::InvokerStorage6<Sig, P1, P2, P3, P4, P5, P6>( - f, p1, p2, p3, p4, p5, p6)); -} + // 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 ), + do_not_bind_functions_with_nonconst_ref); -// Specializations to allow binding all the free arguments in a -// pre-existing base::Callback<>. This does not give full support for -// currying, but is significantly simpler and addresses the use case -// where a base::Callback<> needs to be invoked on another context/thread. -template <typename Sig, typename P1> -base::Closure Bind(const base::Callback<Sig>& callback, const P1& p1) { - return base::Bind(&internal::BindMoreFunc1<Sig, P1>, callback, p1); + // 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); + + return internal::MakeBindStateHolder( + new internal::BindState<RunnableType, RunType, + void(typename internal::CallbackParamTraits<P1>::StorageType)>( + internal::MakeRunnable(functor), p1)); } -template <typename Sig, typename P1, typename P2> -base::Closure Bind(const base::Callback<Sig>& callback, const P1& p1, - const P2& p2) { - return base::Bind(&internal::BindMoreFunc2<Sig, P1, P2>, callback, p1, p2); +template <typename Functor, typename P1, typename P2> +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)> > +Bind(Functor functor, const P1& p1, const P2& p2) { + // 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 ), + 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); + + return internal::MakeBindStateHolder( + new internal::BindState<RunnableType, RunType, + void(typename internal::CallbackParamTraits<P1>::StorageType, + typename internal::CallbackParamTraits<P2>::StorageType)>( + internal::MakeRunnable(functor), p1, p2)); } -template <typename Sig, typename P1, typename P2, typename P3> -base::Closure Bind(const base::Callback<Sig>& callback, const P1& p1, - const P2& p2, const P3& p3) { - return base::Bind(&internal::BindMoreFunc3<Sig, P1, P2, P3>, callback, p1, - p2, p3); +template <typename Functor, typename P1, typename P2, typename P3> +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)> > +Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3) { + // 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 ), + 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); + + return internal::MakeBindStateHolder( + new internal::BindState<RunnableType, RunType, + void(typename internal::CallbackParamTraits<P1>::StorageType, + typename internal::CallbackParamTraits<P2>::StorageType, + typename internal::CallbackParamTraits<P3>::StorageType)>( + internal::MakeRunnable(functor), p1, p2, p3)); } -template <typename Sig, typename P1, typename P2, typename P3, typename P4> -base::Closure Bind(const base::Callback<Sig>& callback, const P1& p1, - const P2& p2, const P3& p3, const P4& p4) { - return base::Bind(&internal::BindMoreFunc4<Sig, P1, P2, P3, P4>, callback, - p1, p2, p3, p4); +template <typename Functor, typename P1, typename P2, typename P3, typename P4> +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)> > +Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4) { + // 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 ), + 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); + + 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)>( + internal::MakeRunnable(functor), p1, p2, p3, p4)); } -template <typename Sig, typename P1, typename P2, typename P3, typename P4, +template <typename Functor, typename P1, typename P2, typename P3, typename P4, typename P5> -base::Closure Bind(const base::Callback<Sig>& callback, const P1& p1, - const P2& p2, const P3& p3, const P4& p4, const P5& p5) { - return base::Bind(&internal::BindMoreFunc5<Sig, P1, P2, P3, P4, P5>, - callback, p1, p2, p3, p4, p5); +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)> > +Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4, + const P5& p5) { + // 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 ), + 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); + + 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)>( + internal::MakeRunnable(functor), p1, p2, p3, p4, p5)); } -template <typename Sig, typename P1, typename P2, typename P3, typename P4, +template <typename Functor, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6> -base::Closure Bind(const base::Callback<Sig>& callback, const P1& p1, - const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6) { - return base::Bind(&internal::BindMoreFunc6<Sig, P1, P2, P3, P4, P5, P6>, - callback, p1, p2, p3, p4, p5, p6); +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)> > +Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4, + const P5& p5, const P6& p6) { + // 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 ), + 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); + + 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)>( + internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6)); } } // namespace base diff --git a/base/bind.h.pump b/base/bind.h.pump index eca00cd..11b4667 100644 --- a/base/bind.h.pump +++ b/base/bind.h.pump @@ -18,7 +18,10 @@ $var MAX_ARITY = 6 #include "base/bind_internal.h" #include "base/callback_internal.h" -// See base/callback.h for how to use these functions. +// See base/callback.h for how to use these functions. If reading the +// implementation, before proceeding further, you should read the top +// comment of base/bind_internal.h for a definition of common terms and +// concepts. // // IMPLEMENTATION NOTE // Though Bind()'s result is meant to be stored in a Callback<> type, it @@ -31,60 +34,88 @@ $var MAX_ARITY = 6 // Each unique combination of (arity, function_type, num_prebound) where // function_type is one of {function, method, const_method} would require // one specialization. We eventually have to do a similar number of -// specializations anyways in the implementation (see the FunctionTraitsN, +// specializations anyways in the implementation (see the Invoker<>, // classes). However, it is avoidable in Bind if we return the result // via an indirection like we do below. +// +// TODO(ajwong): We might be able to avoid this now, but need to test. +// +// It is possible to move most of the COMPILE_ASSERT asserts into BindState<>, +// but it feels a little nicer to have the asserts here so people do not +// need to crack open bind_internal.h. On the other hand, it makes Bind() +// harder to read. namespace base { -$range BOUND 0..MAX_ARITY -$for BOUND [[ -$range BOUND_ARG 1..BOUND +$range ARITY 0..MAX_ARITY +$for ARITY [[ +$range ARG 1..ARITY + +template <typename Functor[[]] +$if ARITY > 0 [[, ]] $for ARG , [[typename P$(ARG)]]> +internal::BindStateHolder< + internal::BindState< + typename internal::FunctorTraits<Functor>::RunnableType, + typename internal::FunctorTraits<Functor>::RunType, + void($for ARG , [[typename internal::CallbackParamTraits<P$(ARG)>::StorageType]])> > +Bind(Functor functor +$if ARITY > 0 [[, ]] $for ARG , [[const P$(ARG)& p$(ARG)]]) { + // 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; + +$if ARITY > 0 [[ + + // 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( + !($for ARG || [[ +is_non_const_reference<typename BoundFunctorTraits::A$(ARG)Type>::value ]]), + do_not_bind_functions_with_nonconst_ref); + +]] -$if BOUND == 0 [[ -template <typename Sig> -internal::InvokerStorageHolder<internal::InvokerStorage0<Sig> > -Bind(Sig f) { - return internal::MakeInvokerStorageHolder( - new internal::InvokerStorage0<Sig>(f)); -} +$for ARG [[ + +$if ARG == 1 [[ + // 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<P$(ARG)>::value, + p$(ARG)_is_refcounted_type_and_needs_scoped_refptr); + COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value || + !is_array<P$(ARG)>::value, + first_bound_argument_to_method_cannot_be_array); ]] $else [[ + COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P$(ARG)>::value, + p$(ARG)_is_refcounted_type_and_needs_scoped_refptr); +]] $$ $if ARG -template <typename Sig, $for BOUND_ARG , [[typename P$(BOUND_ARG)]]> -internal::InvokerStorageHolder<internal::InvokerStorage$(BOUND)<Sig, -$for BOUND_ARG , [[P$(BOUND_ARG)]]> > -Bind(Sig f, $for BOUND_ARG , [[const P$(BOUND_ARG)& p$(BOUND_ARG)]]) { - return internal::MakeInvokerStorageHolder( - new internal::InvokerStorage$(BOUND)<Sig, [[]] -$for BOUND_ARG , [[P$(BOUND_ARG)]]>( - f, $for BOUND_ARG , [[p$(BOUND_ARG)]])); -} +]] $$ $for ARG -]] -]] $$ for BOUND - -// Specializations to allow binding all the free arguments in a -// pre-existing base::Callback<>. This does not give full support for -// currying, but is significantly simpler and addresses the use case -// where a base::Callback<> needs to be invoked on another context/thread. -$for BOUND [[ -$range BOUND_ARG 1..BOUND -$if BOUND != 0 [[ - -template <typename Sig, $for BOUND_ARG , [[typename P$(BOUND_ARG)]]> -base::Closure Bind(const base::Callback<Sig>& callback, [[]] -$for BOUND_ARG , [[const P$(BOUND_ARG)& p$(BOUND_ARG)]]) { - return base::Bind([[]] -&internal::BindMoreFunc$(BOUND)<Sig, $for BOUND_ARG , [[P$(BOUND_ARG)]]>, [[]] -callback, [[]] -$for BOUND_ARG , [[p$(BOUND_ARG)]]); -} -]] + return internal::MakeBindStateHolder( + new internal::BindState<RunnableType, RunType, [[]] +void($for ARG , [[typename internal::CallbackParamTraits<P$(ARG)>::StorageType]])>( + internal::MakeRunnable(functor)[[]] +$if ARITY > 0 [[, ]] $for ARG , [[p$(ARG)]])); +} -]] $$ for BOUND +]] $$ for ARITY } // namespace base diff --git a/base/bind_helpers.h b/base/bind_helpers.h index d7ddb2c..6e0f8fe 100644 --- a/base/bind_helpers.h +++ b/base/bind_helpers.h @@ -198,7 +198,6 @@ class SupportsAddRefAndRelease { static const bool value = sizeof(Check<Base>(0)) == sizeof(Yes); }; - // Helpers to assert that arguments of a recounted type are bound with a // scoped_refptr. template <bool IsClasstype, typename T> @@ -219,6 +218,20 @@ struct UnsafeBindtoRefCountedArg<T*> : UnsafeBindtoRefCountedArgHelper<is_class<T>::value, T> { }; +template <typename T> +class HasIsMethodTag { + typedef char Yes[1]; + typedef char No[2]; + + template <typename U> + static Yes& Check(typename U::IsMethod*); + + template <typename U> + static No& Check(...); + + public: + static const bool value = sizeof(Check<T>(0)) == sizeof(Yes); +}; template <typename T> class UnretainedWrapper { @@ -238,6 +251,20 @@ class ConstRefWrapper { const T* ptr_; }; +template <typename T> +struct IgnoreResultHelper { + explicit IgnoreResultHelper(T functor) : functor_(functor) {} + + T functor_; +}; + +template <typename T> +struct IgnoreResultHelper<Callback<T> > { + explicit IgnoreResultHelper(const Callback<T>& functor) : functor_(functor) {} + + const Callback<T>& functor_; +}; + // An alternate implementation is to avoid the destructive copy, and instead // specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to // a class that is essentially a scoped_ptr<>. @@ -260,61 +287,80 @@ class OwnedWrapper { mutable T* ptr_; }; - // Unwrap the stored parameters for the wrappers above. template <typename T> -T Unwrap(T o) { return o; } +struct UnwrapTraits { + typedef const T& ForwardType; + static ForwardType Unwrap(const T& o) { return o; } +}; template <typename T> -T* Unwrap(UnretainedWrapper<T> unretained) { return unretained.get(); } +struct UnwrapTraits<UnretainedWrapper<T> > { + typedef T* ForwardType; + static ForwardType Unwrap(UnretainedWrapper<T> unretained) { + return unretained.get(); + } +}; template <typename T> -const T& Unwrap(ConstRefWrapper<T> const_ref) { - return const_ref.get(); -} +struct UnwrapTraits<ConstRefWrapper<T> > { + typedef const T& ForwardType; + static ForwardType Unwrap(ConstRefWrapper<T> const_ref) { + return const_ref.get(); + } +}; template <typename T> -T* Unwrap(const scoped_refptr<T>& o) { return o.get(); } +struct UnwrapTraits<scoped_refptr<T> > { + typedef T* ForwardType; + static ForwardType Unwrap(const scoped_refptr<T>& o) { return o.get(); } +}; template <typename T> -const WeakPtr<T>& Unwrap(const WeakPtr<T>& o) { return o; } +struct UnwrapTraits<WeakPtr<T> > { + typedef const WeakPtr<T>& ForwardType; + static ForwardType Unwrap(const WeakPtr<T>& o) { return o; } +}; template <typename T> -T* Unwrap(const OwnedWrapper<T>& o) { - return o.get(); -} +struct UnwrapTraits<OwnedWrapper<T> > { + typedef T* ForwardType; + static ForwardType Unwrap(const OwnedWrapper<T>& o) { + return o.get(); + } +}; // Utility for handling different refcounting semantics in the Bind() // function. -template <typename IsMethod, typename T> +template <bool, typename T> struct MaybeRefcount; template <typename T> -struct MaybeRefcount<base::false_type, T> { +struct MaybeRefcount<false, T> { static void AddRef(const T&) {} static void Release(const T&) {} }; template <typename T, size_t n> -struct MaybeRefcount<base::false_type, T[n]> { +struct MaybeRefcount<false, T[n]> { static void AddRef(const T*) {} static void Release(const T*) {} }; template <typename T> -struct MaybeRefcount<base::true_type, T*> { +struct MaybeRefcount<true, T*> { static void AddRef(T* o) { o->AddRef(); } static void Release(T* o) { o->Release(); } }; template <typename T> -struct MaybeRefcount<base::true_type, UnretainedWrapper<T> > { +struct MaybeRefcount<true, UnretainedWrapper<T> > { static void AddRef(const UnretainedWrapper<T>&) {} static void Release(const UnretainedWrapper<T>&) {} }; template <typename T> -struct MaybeRefcount<base::true_type, OwnedWrapper<T> > { +struct MaybeRefcount<true, OwnedWrapper<T> > { static void AddRef(const OwnedWrapper<T>&) {} static void Release(const OwnedWrapper<T>&) {} }; @@ -322,19 +368,19 @@ struct MaybeRefcount<base::true_type, OwnedWrapper<T> > { // No need to additionally AddRef() and Release() since we are storing a // scoped_refptr<> inside the storage object already. template <typename T> -struct MaybeRefcount<base::true_type, scoped_refptr<T> > { +struct MaybeRefcount<true, scoped_refptr<T> > { static void AddRef(const scoped_refptr<T>& o) {} static void Release(const scoped_refptr<T>& o) {} }; template <typename T> -struct MaybeRefcount<base::true_type, const T*> { +struct MaybeRefcount<true, const T*> { static void AddRef(const T* o) { o->AddRef(); } static void Release(const T* o) { o->Release(); } }; template <typename T> -struct MaybeRefcount<base::true_type, WeakPtr<T> > { +struct MaybeRefcount<true, WeakPtr<T> > { static void AddRef(const WeakPtr<T>&) {} static void Release(const WeakPtr<T>&) {} }; @@ -344,28 +390,55 @@ void VoidReturnAdapter(Callback<R(void)> callback) { callback.Run(); } +// IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a +// method. It is unsed internally by Bind() to select the correct +// InvokeHelper that will no-op itself in the event the WeakPtr<> for +// the target object is invalidated. +// +// P1 should be the type of the object that will be received of the method. +template <bool IsMethod, typename P1> +struct IsWeakMethod : public false_type {}; + +template <typename T> +struct IsWeakMethod<true, WeakPtr<T> > : public true_type {}; + +template <typename T> +struct IsWeakMethod<true, ConstRefWrapper<WeakPtr<T> > > : public true_type {}; + } // namespace internal template <typename T> -inline internal::UnretainedWrapper<T> Unretained(T* o) { +static inline internal::UnretainedWrapper<T> Unretained(T* o) { return internal::UnretainedWrapper<T>(o); } template <typename T> -inline internal::ConstRefWrapper<T> ConstRef(const T& o) { +static inline internal::ConstRefWrapper<T> ConstRef(const T& o) { return internal::ConstRefWrapper<T>(o); } template <typename T> -inline internal::OwnedWrapper<T> Owned(T* o) { +static inline internal::OwnedWrapper<T> Owned(T* o) { return internal::OwnedWrapper<T>(o); } template <typename R> -Closure IgnoreReturn(Callback<R(void)> callback) { +static inline Closure IgnoreReturn(Callback<R(void)> callback) { return Bind(&internal::VoidReturnAdapter<R>, callback); } +template <typename T> +static inline internal::IgnoreResultHelper<T> IgnoreResult(T data) { + return internal::IgnoreResultHelper<T>(data); +} + +template <typename T> +static inline internal::IgnoreResultHelper<Callback<T> > +IgnoreResult(const Callback<T>& data) { + return internal::IgnoreResultHelper<Callback<T> >(data); +} + + } // namespace base #endif // BASE_BIND_HELPERS_H_ diff --git a/base/bind_internal.h b/base/bind_internal.h index 7beba51..6c76d80 100644 --- a/base/bind_internal.h +++ b/base/bind_internal.h @@ -4,6 +4,12 @@ +// 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. @@ -26,2167 +32,2114 @@ namespace base { namespace internal { -// The method by which a function is invoked is determined by 3 different -// dimensions: -// -// 1) The type of function (normal or method). -// 2) The arity of the function. -// 3) The number of bound parameters. +// CONCEPTS: +// Runnable -- A type (really a type class) that has a single Run() method +// and a RunType typedef that corresponds to the type of Run(). +// A Runnable can declare that it should treated like a method +// call by including a typedef named IsMethod. The value of +// this typedef is NOT inspected, only the existence. When a +// Runnable declares itself a method, Bind() will enforce special +// refcounting + WeakPtr handling semantics for the first +// parameter which is expected to be an object. +// Functor -- A copyable type representing something that should be called. +// All function pointers, Callback<>, and Runnables are functors +// even if the invocation syntax differs. +// RunType -- A function type (as opposed to function _pointer_ type) for +// a Run() function. Usually just a convenience typedef. +// (Bound)ArgsType -- A function type that is being (ab)used to store the +// types of set of arguments. The "return" type is always +// void here. We use this hack so that we do not need +// a new type name for each arity of type. (eg., +// BindState1, BindState2). This makes forward +// declarations and friending much much easier. // -// The templates below handle the determination of each of these dimensions. -// In brief: -// -// FunctionTraits<> -- Provides a normalied signature, and other traits. -// InvokerN<> -- Provides a DoInvoke() function that actually executes -// 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<> +// Types: +// RunnableAdapter<> -- Wraps the various "function" pointer types into an +// object that adheres to the Runnable interface. +// There are |3*ARITY| RunnableAdapter types. +// FunctionTraits<> -- Type traits that unwrap a function signature into a +// a set of easier to use typedefs. Used mainly for +// compile time asserts. +// There are |ARITY| FunctionTraits types. +// ForceVoidReturn<> -- Helper class for translating function signatures to +// equivalent forms with a "void" return type. +// There are |ARITY| ForceVoidReturn types. +// FunctorTraits<> -- Type traits used determine the correct RunType and +// RunnableType for a Functor. This is where function +// signature adapters are applied. +// There are |ARITY| ForceVoidReturn types. +// MakeRunnable<> -- Takes a Functor and returns an object in the Runnable +// type class that represents the underlying Functor. +// There are |O(1)| MakeRunnable types. +// InvokeHelper<> -- Take a Runnable + arguments and actully invokes it. +// Handle the differing syntaxes needed for WeakPtr<> support, +// and for ignoring return values. This is separate from +// Invoker to avoid creating multiple version of Invoker<> +// which grows at O(n^2) with the arity. +// There are |k*ARITY| InvokeHelper types. +// Invoker<> -- Unwraps the curried parameters and executes the Runnable. +// There are |(ARITY^2 + ARITY)/2| Invoketypes. +// BindState<> -- Stores the curried parameters, and is the main entry point +// into the Bind() system, doing most of the type resolution. +// There are ARITY BindState types. + + +// RunnableAdapter<> // -// The FunctionTraits<> template determines the type of function, and also -// creates a NormalizedType used to select the InvokerN classes. It turns out -// that syntactically, you only really have 2 variations when invoking a -// funciton pointer: normal, and method. One is invoked func_ptr(arg1). The -// other is invoked (*obj_->method_ptr(arg1)). +// The RunnableAdapter<> templates provide a uniform interface for invoking +// a function pointer, method pointer, or const method pointer. The adapter +// exposes a Run() method with an appropriate signature. Using this wrapper +// allows for writing code that supports all three pointer types without +// undue repetition. Without it, a lot of code would need to be repeated 3 +// times. // -// However, in the type system, there are many more distinctions. In standard -// C++, there's all variations of const, and volatile on the function pointer. -// In Windows, there are additional calling conventions (eg., __stdcall, -// __fastcall, etc.). FunctionTraits<> handles categorizing each of these into -// a normalized signature. +// For method pointers and const method pointers the first argument to Run() +// is considered to be the received of the method. This is similar to STL's +// mem_fun(). // -// Having a NormalizedSignature signature, reduces the combinatoric -// complexity of defintions for the InvokerN<> later. Even though there are -// only 2 syntactic variations on invoking a function, without normalizing the -// signature, there would need to be one specialization of InvokerN for each -// unique (function_type, bound_arg, unbound_args) tuple in order to match all -// function signatures. +// This class also exposes a RunType typedef that is the function type of the +// Run() function. // -// By normalizing the function signature, we reduce function_type to exactly 2. +// If and only if the wrapper contains a method or const method pointer, an +// IsMethod typedef is exposed. The existence of this typedef (NOT the value) +// marks that the wrapper should be considered a method wrapper. -template <typename Sig> -struct FunctionTraits; +template <typename Functor> +class RunnableAdapter; // Function: Arity 0. template <typename R> -struct FunctionTraits<R(*)()> { - typedef R (*NormalizedSig)(); - typedef false_type IsMethod; +class RunnableAdapter<R(*)()> { + public: + typedef R (RunType)(); + + explicit RunnableAdapter(R(*function)()) + : function_(function) { + } - typedef R Return; + R Run() { + return function_(); + } + private: + R (*function_)(); }; // Method: Arity 0. template <typename R, typename T> -struct FunctionTraits<R(T::*)()> { - typedef R (T::*NormalizedSig)(); +class RunnableAdapter<R(T::*)()> { + public: + typedef R (RunType)(T*); typedef true_type IsMethod; - typedef R Return; + explicit RunnableAdapter(R(T::*method)()) + : method_(method) { + } - // Target type for each bound parameter. - typedef T B1; + R Run(T* object) { + return (object->*method_)(); + } + private: + R (T::*method_)(); }; // Const Method: Arity 0. template <typename R, typename T> -struct FunctionTraits<R(T::*)() const> { - typedef R (T::*NormalizedSig)(); +class RunnableAdapter<R(T::*)() const> { + public: + typedef R (RunType)(const T*); typedef true_type IsMethod; - typedef R Return; + explicit RunnableAdapter(R(T::*method)() const) + : method_(method) { + } - // Target type for each bound parameter. - typedef T B1; + R Run(const T* object) { + return (object->*method_)(); + } + private: + R (T::*method_)() const; }; // Function: Arity 1. -template <typename R, typename X1> -struct FunctionTraits<R(*)(X1)> { - typedef R (*NormalizedSig)(X1); - typedef false_type IsMethod; +template <typename R, typename A1> +class RunnableAdapter<R(*)(A1)> { + public: + typedef R (RunType)(A1); - typedef R Return; + explicit RunnableAdapter(R(*function)(A1)) + : function_(function) { + } - // Target type for each bound parameter. - typedef X1 B1; + R Run(typename CallbackParamTraits<A1>::ForwardType a1) { + return function_(a1); + } + private: + R (*function_)(A1); }; // Method: Arity 1. -template <typename R, typename T, typename X1> -struct FunctionTraits<R(T::*)(X1)> { - typedef R (T::*NormalizedSig)(X1); +template <typename R, typename T, typename A1> +class RunnableAdapter<R(T::*)(A1)> { + public: + typedef R (RunType)(T*, A1); typedef true_type IsMethod; - typedef R Return; + explicit RunnableAdapter(R(T::*method)(A1)) + : method_(method) { + } - // Target type for each bound parameter. - typedef T B1; - typedef X1 B2; + R Run(T* object, typename CallbackParamTraits<A1>::ForwardType a1) { + return (object->*method_)(a1); + } + private: + R (T::*method_)(A1); }; // Const Method: Arity 1. -template <typename R, typename T, typename X1> -struct FunctionTraits<R(T::*)(X1) const> { - typedef R (T::*NormalizedSig)(X1); +template <typename R, typename T, typename A1> +class RunnableAdapter<R(T::*)(A1) const> { + public: + typedef R (RunType)(const T*, A1); typedef true_type IsMethod; - typedef R Return; + explicit RunnableAdapter(R(T::*method)(A1) const) + : method_(method) { + } - // Target type for each bound parameter. - typedef T B1; - typedef X1 B2; + R Run(const T* object, typename CallbackParamTraits<A1>::ForwardType a1) { + return (object->*method_)(a1); + } + private: + R (T::*method_)(A1) const; }; // Function: Arity 2. -template <typename R, typename X1, typename X2> -struct FunctionTraits<R(*)(X1, X2)> { - typedef R (*NormalizedSig)(X1, X2); - typedef false_type IsMethod; +template <typename R, typename A1, typename A2> +class RunnableAdapter<R(*)(A1, A2)> { + public: + typedef R (RunType)(A1, A2); - typedef R Return; + explicit RunnableAdapter(R(*function)(A1, A2)) + : function_(function) { + } - // Target type for each bound parameter. - typedef X1 B1; - typedef X2 B2; + R Run(typename CallbackParamTraits<A1>::ForwardType a1, + typename CallbackParamTraits<A2>::ForwardType a2) { + return function_(a1, a2); + } + private: + R (*function_)(A1, A2); }; // Method: Arity 2. -template <typename R, typename T, typename X1, typename X2> -struct FunctionTraits<R(T::*)(X1, X2)> { - typedef R (T::*NormalizedSig)(X1, X2); +template <typename R, typename T, typename A1, typename A2> +class RunnableAdapter<R(T::*)(A1, A2)> { + public: + typedef R (RunType)(T*, A1, A2); typedef true_type IsMethod; - typedef R Return; + explicit RunnableAdapter(R(T::*method)(A1, A2)) + : method_(method) { + } - // Target type for each bound parameter. - typedef T B1; - typedef X1 B2; - typedef X2 B3; + R Run(T* object, typename CallbackParamTraits<A1>::ForwardType a1, + typename CallbackParamTraits<A2>::ForwardType a2) { + return (object->*method_)(a1, a2); + } + private: + R (T::*method_)(A1, A2); }; // Const Method: Arity 2. -template <typename R, typename T, typename X1, typename X2> -struct FunctionTraits<R(T::*)(X1, X2) const> { - typedef R (T::*NormalizedSig)(X1, X2); +template <typename R, typename T, typename A1, typename A2> +class RunnableAdapter<R(T::*)(A1, A2) const> { + public: + typedef R (RunType)(const T*, A1, A2); typedef true_type IsMethod; - typedef R Return; + explicit RunnableAdapter(R(T::*method)(A1, A2) const) + : method_(method) { + } - // Target type for each bound parameter. - typedef T B1; - typedef X1 B2; - typedef X2 B3; + R Run(const T* object, typename CallbackParamTraits<A1>::ForwardType a1, + typename CallbackParamTraits<A2>::ForwardType a2) { + return (object->*method_)(a1, a2); + } + private: + R (T::*method_)(A1, A2) const; }; // Function: Arity 3. -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; +template <typename R, typename A1, typename A2, typename A3> +class RunnableAdapter<R(*)(A1, A2, A3)> { + public: + typedef R (RunType)(A1, A2, A3); - typedef R Return; + explicit RunnableAdapter(R(*function)(A1, A2, A3)) + : function_(function) { + } - // Target type for each bound parameter. - typedef X1 B1; - typedef X2 B2; - typedef X3 B3; + R Run(typename CallbackParamTraits<A1>::ForwardType a1, + typename CallbackParamTraits<A2>::ForwardType a2, + typename CallbackParamTraits<A3>::ForwardType a3) { + return function_(a1, a2, a3); + } + private: + R (*function_)(A1, A2, A3); }; // Method: Arity 3. -template <typename R, typename T, typename X1, typename X2, typename X3> -struct FunctionTraits<R(T::*)(X1, X2, X3)> { - typedef R (T::*NormalizedSig)(X1, X2, X3); +template <typename R, typename T, typename A1, typename A2, typename A3> +class RunnableAdapter<R(T::*)(A1, A2, A3)> { + public: + typedef R (RunType)(T*, A1, A2, A3); typedef true_type IsMethod; - typedef R Return; + explicit RunnableAdapter(R(T::*method)(A1, A2, A3)) + : method_(method) { + } - // Target type for each bound parameter. - typedef T B1; - typedef X1 B2; - typedef X2 B3; - typedef X3 B4; + R Run(T* object, typename CallbackParamTraits<A1>::ForwardType a1, + typename CallbackParamTraits<A2>::ForwardType a2, + typename CallbackParamTraits<A3>::ForwardType a3) { + return (object->*method_)(a1, a2, a3); + } + private: + R (T::*method_)(A1, A2, A3); }; // Const Method: Arity 3. -template <typename R, typename T, typename X1, typename X2, typename X3> -struct FunctionTraits<R(T::*)(X1, X2, X3) const> { - typedef R (T::*NormalizedSig)(X1, X2, X3); +template <typename R, typename T, typename A1, typename A2, typename A3> +class RunnableAdapter<R(T::*)(A1, A2, A3) const> { + public: + typedef R (RunType)(const T*, A1, A2, A3); typedef true_type IsMethod; - typedef R Return; + explicit RunnableAdapter(R(T::*method)(A1, A2, A3) const) + : method_(method) { + } - // Target type for each bound parameter. - typedef T B1; - typedef X1 B2; - typedef X2 B3; - typedef X3 B4; + R Run(const T* object, typename CallbackParamTraits<A1>::ForwardType a1, + typename CallbackParamTraits<A2>::ForwardType a2, + typename CallbackParamTraits<A3>::ForwardType a3) { + return (object->*method_)(a1, a2, a3); + } + private: + R (T::*method_)(A1, A2, A3) const; }; // Function: Arity 4. -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; +template <typename R, typename A1, typename A2, typename A3, typename A4> +class RunnableAdapter<R(*)(A1, A2, A3, A4)> { + public: + typedef R (RunType)(A1, A2, A3, A4); - typedef R Return; + explicit RunnableAdapter(R(*function)(A1, A2, A3, A4)) + : function_(function) { + } - // Target type for each bound parameter. - typedef X1 B1; - typedef X2 B2; - typedef X3 B3; - typedef X4 B4; + R Run(typename CallbackParamTraits<A1>::ForwardType a1, + typename CallbackParamTraits<A2>::ForwardType a2, + typename CallbackParamTraits<A3>::ForwardType a3, + typename CallbackParamTraits<A4>::ForwardType a4) { + return function_(a1, a2, a3, a4); + } + private: + R (*function_)(A1, A2, A3, A4); }; // Method: Arity 4. -template <typename R, typename T, typename X1, typename X2, typename X3, - typename X4> -struct FunctionTraits<R(T::*)(X1, X2, X3, X4)> { - typedef R (T::*NormalizedSig)(X1, X2, X3, X4); +template <typename R, typename T, typename A1, typename A2, typename A3, + typename A4> +class RunnableAdapter<R(T::*)(A1, A2, A3, A4)> { + public: + typedef R (RunType)(T*, A1, A2, A3, A4); typedef true_type IsMethod; - typedef R Return; + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4)) + : method_(method) { + } - // Target type for each bound parameter. - typedef T B1; - typedef X1 B2; - typedef X2 B3; - typedef X3 B4; - typedef X4 B5; + R Run(T* object, typename CallbackParamTraits<A1>::ForwardType a1, + typename CallbackParamTraits<A2>::ForwardType a2, + typename CallbackParamTraits<A3>::ForwardType a3, + typename CallbackParamTraits<A4>::ForwardType a4) { + return (object->*method_)(a1, a2, a3, a4); + } + private: + R (T::*method_)(A1, A2, A3, A4); }; // Const Method: Arity 4. -template <typename R, typename T, typename X1, typename X2, typename X3, - typename X4> -struct FunctionTraits<R(T::*)(X1, X2, X3, X4) const> { - typedef R (T::*NormalizedSig)(X1, X2, X3, X4); +template <typename R, typename T, typename A1, typename A2, typename A3, + typename A4> +class RunnableAdapter<R(T::*)(A1, A2, A3, A4) const> { + public: + typedef R (RunType)(const T*, A1, A2, A3, A4); typedef true_type IsMethod; - typedef R Return; + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4) const) + : method_(method) { + } - // Target type for each bound parameter. - typedef T B1; - typedef X1 B2; - typedef X2 B3; - typedef X3 B4; - typedef X4 B5; + 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) { + return (object->*method_)(a1, a2, a3, a4); + } + private: + R (T::*method_)(A1, A2, A3, A4) const; }; // Function: Arity 5. -template <typename R, typename X1, typename X2, typename X3, typename X4, - typename X5> -struct FunctionTraits<R(*)(X1, X2, X3, X4, X5)> { - typedef R (*NormalizedSig)(X1, X2, X3, X4, X5); - typedef false_type IsMethod; +template <typename R, typename A1, typename A2, typename A3, typename A4, + typename A5> +class RunnableAdapter<R(*)(A1, A2, A3, A4, A5)> { + public: + typedef R (RunType)(A1, A2, A3, A4, A5); - typedef R Return; + explicit RunnableAdapter(R(*function)(A1, A2, A3, A4, A5)) + : function_(function) { + } - // Target type for each bound parameter. - typedef X1 B1; - typedef X2 B2; - typedef X3 B3; - typedef X4 B4; - typedef X5 B5; + 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) { + return function_(a1, a2, a3, a4, a5); + } + private: + R (*function_)(A1, A2, A3, A4, A5); }; // Method: Arity 5. -template <typename R, typename T, typename X1, typename X2, typename X3, - typename X4, typename X5> -struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5)> { - typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5); +template <typename R, typename T, typename A1, typename A2, typename A3, + typename A4, typename A5> +class RunnableAdapter<R(T::*)(A1, A2, A3, A4, A5)> { + public: + typedef R (RunType)(T*, A1, A2, A3, A4, A5); typedef true_type IsMethod; - typedef R Return; + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5)) + : method_(method) { + } - // Target type for each bound parameter. - typedef T B1; - typedef X1 B2; - typedef X2 B3; - typedef X3 B4; - typedef X4 B5; - typedef X5 B6; + 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) { + return (object->*method_)(a1, a2, a3, a4, a5); + } + private: + R (T::*method_)(A1, A2, A3, A4, A5); }; // Const Method: Arity 5. -template <typename R, typename T, typename X1, typename X2, typename X3, - typename X4, typename X5> -struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5) const> { - typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5); +template <typename R, typename T, typename A1, typename A2, typename A3, + typename A4, typename A5> +class RunnableAdapter<R(T::*)(A1, A2, A3, A4, A5) const> { + public: + typedef R (RunType)(const T*, A1, A2, A3, A4, A5); typedef true_type IsMethod; - typedef R Return; + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5) const) + : method_(method) { + } - // Target type for each bound parameter. - typedef T B1; - typedef X1 B2; - typedef X2 B3; - typedef X3 B4; - typedef X4 B5; - typedef X5 B6; + 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) { + return (object->*method_)(a1, a2, a3, a4, a5); + } + private: + R (T::*method_)(A1, A2, A3, A4, A5) const; }; // Function: Arity 6. -template <typename R, typename X1, typename X2, typename X3, typename X4, - typename X5, typename X6> -struct FunctionTraits<R(*)(X1, X2, X3, X4, X5, X6)> { - typedef R (*NormalizedSig)(X1, X2, X3, X4, X5, X6); - typedef false_type IsMethod; +template <typename R, typename A1, typename A2, typename A3, typename A4, + typename A5, typename A6> +class RunnableAdapter<R(*)(A1, A2, A3, A4, A5, A6)> { + public: + typedef R (RunType)(A1, A2, A3, A4, A5, A6); - typedef R Return; + explicit RunnableAdapter(R(*function)(A1, A2, A3, A4, A5, A6)) + : function_(function) { + } - // Target type for each bound parameter. - typedef X1 B1; - typedef X2 B2; - typedef X3 B3; - typedef X4 B4; - typedef X5 B5; - typedef X6 B6; + 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) { + return function_(a1, a2, a3, a4, a5, a6); + } + private: + R (*function_)(A1, A2, A3, A4, A5, A6); }; // Method: Arity 6. -template <typename R, typename T, typename X1, typename X2, typename X3, - typename X4, typename X5, typename X6> -struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5, X6)> { - typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5, X6); +template <typename R, typename T, typename A1, typename A2, typename A3, + typename A4, typename A5, typename A6> +class RunnableAdapter<R(T::*)(A1, A2, A3, A4, A5, A6)> { + public: + typedef R (RunType)(T*, A1, A2, A3, A4, A5, A6); typedef true_type IsMethod; - typedef R Return; + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5, A6)) + : method_(method) { + } - // Target type for each bound parameter. - typedef T B1; - typedef X1 B2; - typedef X2 B3; - typedef X3 B4; - typedef X4 B5; - typedef X5 B6; - typedef X6 B7; + 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) { + return (object->*method_)(a1, a2, a3, a4, a5, a6); + } + private: + R (T::*method_)(A1, A2, A3, A4, A5, A6); }; // Const Method: Arity 6. -template <typename R, typename T, typename X1, typename X2, typename X3, - typename X4, typename X5, typename X6> -struct FunctionTraits<R(T::*)(X1, X2, X3, X4, X5, X6) const> { - typedef R (T::*NormalizedSig)(X1, X2, X3, X4, X5, X6); +template <typename R, typename T, typename A1, typename A2, typename A3, + typename A4, typename A5, typename A6> +class RunnableAdapter<R(T::*)(A1, A2, A3, A4, A5, A6) const> { + public: + typedef R (RunType)(const T*, A1, A2, A3, A4, A5, A6); typedef true_type IsMethod; - typedef R Return; + explicit RunnableAdapter(R(T::*method)(A1, A2, A3, A4, A5, A6) const) + : method_(method) { + } - // Target type for each bound parameter. - typedef T B1; - typedef X1 B2; - typedef X2 B3; - typedef X3 B4; - typedef X4 B5; - typedef X5 B6; - typedef X6 B7; + 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) { + return (object->*method_)(a1, a2, a3, a4, a5, a6); + } + private: + R (T::*method_)(A1, A2, A3, A4, A5, A6) const; }; -// InvokerN<> -// -// The InvokerN templates contain a static DoInvoke() function that is the key -// to implementing type erasure in the Callback() classes. -// -// DoInvoke() is a static function with a fixed signature that is independent -// of StorageType; its first argument is a pointer to the non-templated common -// baseclass of StorageType. This lets us store pointer to DoInvoke() in a -// function pointer that has knowledge of the specific StorageType, and thus -// no knowledge of the bound function and bound parameter types. -// -// As long as we ensure that DoInvoke() is only used with pointers there were -// upcasted from the correct StorageType, we can be sure that execution is -// safe. + +// FunctionTraits<> // -// The InvokerN templates are the only point that knows the number of bound -// and unbound arguments. This is intentional because it allows the other -// templates classes in the system to only have as many specializations as -// the max arity of function we wish to support. +// Breaks a function signature apart into typedefs for easier introspection. +template <typename Sig> +struct FunctionTraits; -template <bool IsWeak, typename StorageType, typename NormalizedSig> -struct Invoker0; +template <typename R> +struct FunctionTraits<R()> { + typedef R ReturnType; +}; -// Function: Arity 0 -> 0. -template <typename StorageType, typename R> -struct Invoker0<false, StorageType, R(*)()> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*); +template <typename R, typename A1> +struct FunctionTraits<R(A1)> { + typedef R ReturnType; + typedef A1 A1Type; +}; - static R DoInvoke(InvokerStorageBase* base) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(); - } +template <typename R, typename A1, typename A2> +struct FunctionTraits<R(A1, A2)> { + typedef R ReturnType; + typedef A1 A1Type; + typedef A2 A2Type; }; -// Function: Arity 1 -> 1. -template <typename StorageType, typename R,typename X1> -struct Invoker0<false, StorageType, R(*)(X1)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X1>::ForwardType); +template <typename R, typename A1, typename A2, typename A3> +struct FunctionTraits<R(A1, A2, A3)> { + typedef R ReturnType; + typedef A1 A1Type; + typedef A2 A2Type; + typedef A3 A3Type; +}; - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X1>::ForwardType x1) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(x1); - } +template <typename R, typename A1, typename A2, typename A3, typename A4> +struct FunctionTraits<R(A1, A2, A3, A4)> { + typedef R ReturnType; + typedef A1 A1Type; + typedef A2 A2Type; + typedef A3 A3Type; + typedef A4 A4Type; }; -// Function: Arity 2 -> 2. -template <typename StorageType, typename R,typename X1, typename X2> -struct Invoker0<false, StorageType, R(*)(X1, X2)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X1>::ForwardType, - typename internal::ParamTraits<X2>::ForwardType); +template <typename R, typename A1, typename A2, typename A3, typename A4, + typename A5> +struct FunctionTraits<R(A1, A2, A3, A4, A5)> { + typedef R ReturnType; + typedef A1 A1Type; + typedef A2 A2Type; + typedef A3 A3Type; + typedef A4 A4Type; + typedef A5 A5Type; +}; - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X1>::ForwardType x1, - typename internal::ParamTraits<X2>::ForwardType x2) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(x1, x2); - } +template <typename R, typename A1, typename A2, typename A3, typename A4, + typename A5, typename A6> +struct FunctionTraits<R(A1, A2, A3, A4, A5, A6)> { + typedef R ReturnType; + typedef A1 A1Type; + typedef A2 A2Type; + typedef A3 A3Type; + typedef A4 A4Type; + typedef A5 A5Type; + typedef A6 A6Type; }; -// Function: Arity 3 -> 3. -template <typename StorageType, typename R,typename X1, typename X2, - typename X3> -struct Invoker0<false, StorageType, R(*)(X1, X2, X3)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X1>::ForwardType, - typename internal::ParamTraits<X2>::ForwardType, - typename internal::ParamTraits<X3>::ForwardType); - static R 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); - return invoker->f_(x1, x2, x3); - } +// ForceVoidReturn<> +// +// Set of templates that support forcing the function return type to void. +template <typename Sig> +struct ForceVoidReturn; + +template <typename R> +struct ForceVoidReturn<R()> { + typedef void(RunType)(); }; -// Function: Arity 4 -> 4. -template <typename StorageType, typename R,typename X1, typename X2, - typename X3, typename X4> -struct Invoker0<false, StorageType, R(*)(X1, X2, X3, X4)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X1>::ForwardType, - typename internal::ParamTraits<X2>::ForwardType, - typename internal::ParamTraits<X3>::ForwardType, - typename internal::ParamTraits<X4>::ForwardType); +template <typename R, typename A1> +struct ForceVoidReturn<R(A1)> { + typedef void(RunType)(A1); +}; - static R 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); - return invoker->f_(x1, x2, x3, x4); - } +template <typename R, typename A1, typename A2> +struct ForceVoidReturn<R(A1, A2)> { + typedef void(RunType)(A1, A2); }; -// Function: Arity 5 -> 5. -template <typename StorageType, typename R,typename X1, typename X2, - typename X3, typename X4, typename X5> -struct Invoker0<false, StorageType, R(*)(X1, X2, X3, X4, X5)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X1>::ForwardType, - typename internal::ParamTraits<X2>::ForwardType, - typename internal::ParamTraits<X3>::ForwardType, - typename internal::ParamTraits<X4>::ForwardType, - typename internal::ParamTraits<X5>::ForwardType); - - static R 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); - return invoker->f_(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<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X1>::ForwardType, - typename internal::ParamTraits<X2>::ForwardType, - typename internal::ParamTraits<X3>::ForwardType, - typename internal::ParamTraits<X4>::ForwardType, - typename internal::ParamTraits<X5>::ForwardType, - typename internal::ParamTraits<X6>::ForwardType); - - static R 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, - typename internal::ParamTraits<X6>::ForwardType x6) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(x1, x2, x3, x4, x5, x6); - } -}; - -template <bool IsWeak, typename StorageType, typename NormalizedSig> -struct Invoker1; - -// Function: Arity 1 -> 0. -template <typename StorageType, typename R,typename X1> -struct Invoker1<false, StorageType, R(*)(X1)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*); +template <typename R, typename A1, typename A2, typename A3> +struct ForceVoidReturn<R(A1, A2, A3)> { + typedef void(RunType)(A1, A2, A3); +}; - static R DoInvoke(InvokerStorageBase* base) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(Unwrap(invoker->p1_)); - } +template <typename R, typename A1, typename A2, typename A3, typename A4> +struct ForceVoidReturn<R(A1, A2, A3, A4)> { + typedef void(RunType)(A1, A2, A3, A4); }; -// Method: Arity 0 -> 0. -template <typename StorageType, typename R, typename T> -struct Invoker1<false, StorageType, R(T::*)()> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*); +template <typename R, typename A1, typename A2, typename A3, typename A4, + typename A5> +struct ForceVoidReturn<R(A1, A2, A3, A4, A5)> { + typedef void(RunType)(A1, A2, A3, A4, A5); +}; - static R DoInvoke(InvokerStorageBase* base) { - StorageType* invoker = static_cast<StorageType*>(base); - return (Unwrap(invoker->p1_)->*invoker->f_)(); - } +template <typename R, typename A1, typename A2, typename A3, typename A4, + typename A5, typename A6> +struct ForceVoidReturn<R(A1, A2, A3, A4, A5, A6)> { + typedef void(RunType)(A1, A2, A3, A4, A5, A6); }; -// WeakPtr Method: Arity 0 -> 0. -template <typename StorageType, typename T> -struct Invoker1<true, StorageType, void(T::*)()> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*); - 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_)(); - } +// FunctorTraits<> +// +// See description at top of file. +template <typename T> +struct FunctorTraits { + typedef RunnableAdapter<T> RunnableType; + typedef typename RunnableType::RunType RunType; }; -// Function: Arity 2 -> 1. -template <typename StorageType, typename R,typename X1, typename X2> -struct Invoker1<false, StorageType, R(*)(X1, X2)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X2>::ForwardType); +template <typename T> +struct FunctorTraits<IgnoreResultHelper<T> > { + typedef typename FunctorTraits<T>::RunnableType RunnableType; + typedef typename ForceVoidReturn< + typename RunnableType::RunType>::RunType RunType; +}; - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X2>::ForwardType x2) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(Unwrap(invoker->p1_), x2); - } +template <typename T> +struct FunctorTraits<Callback<T> > { + typedef Callback<T> RunnableType; + typedef typename Callback<T>::RunType RunType; }; -// Method: Arity 1 -> 1. -template <typename StorageType, typename R, typename T, typename X1> -struct Invoker1<false, StorageType, R(T::*)(X1)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X1>::ForwardType); - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X1>::ForwardType x1) { - StorageType* invoker = static_cast<StorageType*>(base); - return (Unwrap(invoker->p1_)->*invoker->f_)(x1); - } -}; +// MakeRunnable<> +// +// Converts a passed in functor to a RunnableType using type inference. -// WeakPtr Method: Arity 1 -> 1. -template <typename StorageType, typename T, typename X1> -struct Invoker1<true, StorageType, void(T::*)(X1)> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X1>::ForwardType); +template <typename T> +typename FunctorTraits<T>::RunnableType MakeRunnable(const T& t) { + return RunnableAdapter<T>(t); +} - 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); +template <typename T> +typename FunctorTraits<T>::RunnableType +MakeRunnable(const IgnoreResultHelper<T>& t) { + return MakeRunnable(t.functor_); +} + +template <typename T> +const typename FunctorTraits<Callback<T> >::RunnableType& +MakeRunnable(const Callback<T>& t) { + return t; +} + + +// InvokeHelper<> +// +// There are 3 logical InvokeHelper<> specializations: normal, void-return, +// WeakCalls. +// +// The normal type just calls the underlying runnable. +// +// We need a InvokeHelper to handle void return types in order to support +// IgnoreResult(). Normally, if the Runnable's RunType had a void return, +// the template system would just accept "return functor.Run()" ignoring +// the fact that a void function is being used with return. This piece of +// sugar breaks though when the Runnable's RunType is not void. Thus, we +// need a partial specialization to change the syntax to drop the "return" +// from the invocation call. +// +// WeakCalls similarly need special syntax that is applied to the first +// argument to check if they should no-op themselves. +template <bool IsWeakCall, typename ReturnType, typename Runnable, + typename ArgsType> +struct InvokeHelper; + +template <typename ReturnType, typename Runnable> +struct InvokeHelper<false, ReturnType, Runnable, + void()> { + static ReturnType MakeItSo(Runnable runnable) { + return runnable.Run(); } }; -// Function: Arity 3 -> 2. -template <typename StorageType, typename R,typename X1, typename X2, - typename X3> -struct Invoker1<false, StorageType, R(*)(X1, X2, X3)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X2>::ForwardType, - typename internal::ParamTraits<X3>::ForwardType); - - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X2>::ForwardType x2, - typename internal::ParamTraits<X3>::ForwardType x3) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(Unwrap(invoker->p1_), x2, x3); - } -}; - -// Method: Arity 2 -> 2. -template <typename StorageType, typename R, typename T, typename X1, - typename X2> -struct Invoker1<false, StorageType, R(T::*)(X1, X2)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X1>::ForwardType, - typename internal::ParamTraits<X2>::ForwardType); - - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X1>::ForwardType x1, - typename internal::ParamTraits<X2>::ForwardType x2) { - StorageType* invoker = static_cast<StorageType*>(base); - return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2); - } -}; - -// WeakPtr Method: Arity 2 -> 2. -template <typename StorageType, typename T, typename X1, typename X2> -struct Invoker1<true, StorageType, void(T::*)(X1, X2)> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X1>::ForwardType, - typename internal::ParamTraits<X2>::ForwardType); - - 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); +template <typename Runnable> +struct InvokeHelper<false, void, Runnable, + void()> { + static void MakeItSo(Runnable runnable) { + runnable.Run(); } }; -// Function: Arity 4 -> 3. -template <typename StorageType, typename R,typename X1, typename X2, - typename X3, typename X4> -struct Invoker1<false, StorageType, R(*)(X1, X2, X3, X4)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X2>::ForwardType, - typename internal::ParamTraits<X3>::ForwardType, - typename internal::ParamTraits<X4>::ForwardType); - - static R 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); - return invoker->f_(Unwrap(invoker->p1_), x2, x3, x4); - } -}; - -// Method: Arity 3 -> 3. -template <typename StorageType, typename R, typename T, typename X1, - typename X2, typename X3> -struct Invoker1<false, StorageType, R(T::*)(X1, X2, X3)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X1>::ForwardType, - typename internal::ParamTraits<X2>::ForwardType, - typename internal::ParamTraits<X3>::ForwardType); - - static R 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); - return (Unwrap(invoker->p1_)->*invoker->f_)(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)> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X1>::ForwardType, - typename internal::ParamTraits<X2>::ForwardType, - typename internal::ParamTraits<X3>::ForwardType); - - 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); +template <typename ReturnType, typename Runnable,typename A1> +struct InvokeHelper<false, ReturnType, Runnable, + void(A1)> { + static ReturnType MakeItSo(Runnable runnable, A1 a1) { + return runnable.Run(a1); } }; -// Function: Arity 5 -> 4. -template <typename StorageType, typename R,typename X1, typename X2, - typename X3, typename X4, typename X5> -struct Invoker1<false, StorageType, R(*)(X1, X2, X3, X4, X5)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X2>::ForwardType, - typename internal::ParamTraits<X3>::ForwardType, - typename internal::ParamTraits<X4>::ForwardType, - typename internal::ParamTraits<X5>::ForwardType); - - static R 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); - return invoker->f_(Unwrap(invoker->p1_), 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<false, StorageType, R(T::*)(X1, X2, X3, X4)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X1>::ForwardType, - typename internal::ParamTraits<X2>::ForwardType, - typename internal::ParamTraits<X3>::ForwardType, - typename internal::ParamTraits<X4>::ForwardType); - - static R 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); - return (Unwrap(invoker->p1_)->*invoker->f_)(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)> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X1>::ForwardType, - typename internal::ParamTraits<X2>::ForwardType, - typename internal::ParamTraits<X3>::ForwardType, - typename internal::ParamTraits<X4>::ForwardType); - - 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); +template <typename Runnable,typename A1> +struct InvokeHelper<false, void, Runnable, + void(A1)> { + static void MakeItSo(Runnable runnable, A1 a1) { + runnable.Run(a1); } }; -// Function: Arity 6 -> 5. -template <typename StorageType, typename R,typename X1, typename X2, - typename X3, typename X4, typename X5, typename X6> -struct Invoker1<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X2>::ForwardType, - typename internal::ParamTraits<X3>::ForwardType, - typename internal::ParamTraits<X4>::ForwardType, - typename internal::ParamTraits<X5>::ForwardType, - typename internal::ParamTraits<X6>::ForwardType); - - static R 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, - typename internal::ParamTraits<X6>::ForwardType x6) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(Unwrap(invoker->p1_), 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<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X1>::ForwardType, - typename internal::ParamTraits<X2>::ForwardType, - typename internal::ParamTraits<X3>::ForwardType, - typename internal::ParamTraits<X4>::ForwardType, - typename internal::ParamTraits<X5>::ForwardType); - - static R 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); - return (Unwrap(invoker->p1_)->*invoker->f_)(x1, x2, x3, x4, x5); - } -}; - -// 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)> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X1>::ForwardType, - typename internal::ParamTraits<X2>::ForwardType, - typename internal::ParamTraits<X3>::ForwardType, - typename internal::ParamTraits<X4>::ForwardType, - typename internal::ParamTraits<X5>::ForwardType); - - 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()) { +template <typename Runnable, typename A1> +struct InvokeHelper<true, void, Runnable, + void(A1)> { + static void MakeItSo(Runnable runnable, A1 a1) { + if (!a1.get()) { return; } - (weak_ptr->*invoker->f_)(x1, x2, x3, x4, x5); + + runnable.Run(a1); } }; -template <bool IsWeak, typename StorageType, typename NormalizedSig> -struct Invoker2; - -// Function: Arity 2 -> 0. -template <typename StorageType, typename R,typename X1, typename X2> -struct Invoker2<false, StorageType, R(*)(X1, X2)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*); - - static R DoInvoke(InvokerStorageBase* base) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_)); +template <typename ReturnType, typename Runnable,typename A1, typename A2> +struct InvokeHelper<false, ReturnType, Runnable, + void(A1, A2)> { + static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2) { + return runnable.Run(a1, a2); } }; -// Method: Arity 1 -> 0. -template <typename StorageType, typename R, typename T, typename X1> -struct Invoker2<false, StorageType, R(T::*)(X1)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*); - - static R DoInvoke(InvokerStorageBase* base) { - StorageType* invoker = static_cast<StorageType*>(base); - return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_)); +template <typename Runnable,typename A1, typename A2> +struct InvokeHelper<false, void, Runnable, + void(A1, A2)> { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2) { + runnable.Run(a1, a2); } }; -// WeakPtr Method: Arity 1 -> 0. -template <typename StorageType, typename T, typename X1> -struct Invoker2<true, StorageType, void(T::*)(X1)> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*); - - static void DoInvoke(InvokerStorageBase* base) { - StorageType* invoker = static_cast<StorageType*>(base); - typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; - if (!weak_ptr.get()) { +template <typename Runnable, typename A1, typename A2> +struct InvokeHelper<true, void, Runnable, + void(A1, A2)> { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2) { + if (!a1.get()) { return; } - (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_)); + + runnable.Run(a1, a2); } }; -// Function: Arity 3 -> 1. -template <typename StorageType, typename R,typename X1, typename X2, - typename X3> -struct Invoker2<false, StorageType, R(*)(X1, X2, X3)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X3>::ForwardType); - - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X3>::ForwardType x3) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), x3); +template <typename ReturnType, typename Runnable,typename A1, typename A2, + typename A3> +struct InvokeHelper<false, ReturnType, Runnable, + void(A1, A2, A3)> { + static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3) { + return runnable.Run(a1, a2, a3); } }; -// Method: Arity 2 -> 1. -template <typename StorageType, typename R, typename T, typename X1, - typename X2> -struct Invoker2<false, StorageType, R(T::*)(X1, X2)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X2>::ForwardType); - - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X2>::ForwardType x2) { - StorageType* invoker = static_cast<StorageType*>(base); - return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2); +template <typename Runnable,typename A1, typename A2, typename A3> +struct InvokeHelper<false, void, Runnable, + void(A1, A2, A3)> { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3) { + runnable.Run(a1, a2, a3); } }; -// WeakPtr Method: Arity 2 -> 1. -template <typename StorageType, typename T, typename X1, typename X2> -struct Invoker2<true, StorageType, void(T::*)(X1, X2)> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X2>::ForwardType); - - 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()) { +template <typename Runnable, typename A1, typename A2, typename A3> +struct InvokeHelper<true, void, Runnable, + void(A1, A2, A3)> { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3) { + if (!a1.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<false, StorageType, R(*)(X1, X2, X3, X4)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X3>::ForwardType, - typename internal::ParamTraits<X4>::ForwardType); - - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X3>::ForwardType x3, - typename internal::ParamTraits<X4>::ForwardType x4) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), x3, x4); + runnable.Run(a1, a2, a3); } }; -// Method: Arity 3 -> 2. -template <typename StorageType, typename R, typename T, typename X1, - typename X2, typename X3> -struct Invoker2<false, StorageType, R(T::*)(X1, X2, X3)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X2>::ForwardType, - typename internal::ParamTraits<X3>::ForwardType); - - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X2>::ForwardType x2, - typename internal::ParamTraits<X3>::ForwardType x3) { - StorageType* invoker = static_cast<StorageType*>(base); - return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2, x3); +template <typename ReturnType, typename Runnable,typename A1, typename A2, + typename A3, typename A4> +struct InvokeHelper<false, ReturnType, Runnable, + void(A1, A2, A3, A4)> { + static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4) { + return runnable.Run(a1, a2, a3, a4); } }; -// 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)> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X2>::ForwardType, - typename internal::ParamTraits<X3>::ForwardType); - - 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); +template <typename Runnable,typename A1, typename A2, typename A3, typename A4> +struct InvokeHelper<false, void, Runnable, + void(A1, A2, A3, A4)> { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4) { + runnable.Run(a1, a2, a3, a4); } }; -// Function: Arity 5 -> 3. -template <typename StorageType, typename R,typename X1, typename X2, - typename X3, typename X4, typename X5> -struct Invoker2<false, StorageType, R(*)(X1, X2, X3, X4, X5)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X3>::ForwardType, - typename internal::ParamTraits<X4>::ForwardType, - typename internal::ParamTraits<X5>::ForwardType); - - static R 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); - return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), x3, x4, x5); - } -}; - -// Method: Arity 4 -> 3. -template <typename StorageType, typename R, typename T, typename X1, - typename X2, typename X3, typename X4> -struct Invoker2<false, StorageType, R(T::*)(X1, X2, X3, X4)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X2>::ForwardType, - typename internal::ParamTraits<X3>::ForwardType, - typename internal::ParamTraits<X4>::ForwardType); - - static R 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); - return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), 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)> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X2>::ForwardType, - typename internal::ParamTraits<X3>::ForwardType, - typename internal::ParamTraits<X4>::ForwardType); - - 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()) { +template <typename Runnable, typename A1, typename A2, typename A3, typename A4> +struct InvokeHelper<true, void, Runnable, + void(A1, A2, A3, A4)> { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4) { + if (!a1.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<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X3>::ForwardType, - typename internal::ParamTraits<X4>::ForwardType, - typename internal::ParamTraits<X5>::ForwardType, - typename internal::ParamTraits<X6>::ForwardType); - - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X3>::ForwardType x3, - typename internal::ParamTraits<X4>::ForwardType x4, - typename internal::ParamTraits<X5>::ForwardType x5, - typename internal::ParamTraits<X6>::ForwardType x6) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), 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<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X2>::ForwardType, - typename internal::ParamTraits<X3>::ForwardType, - typename internal::ParamTraits<X4>::ForwardType, - typename internal::ParamTraits<X5>::ForwardType); - - static R 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); - return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), x2, x3, - x4, x5); - } -}; - -// 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)> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X2>::ForwardType, - typename internal::ParamTraits<X3>::ForwardType, - typename internal::ParamTraits<X4>::ForwardType, - typename internal::ParamTraits<X5>::ForwardType); - - 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); + runnable.Run(a1, a2, a3, a4); } }; -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<false, StorageType, R(*)(X1, X2, X3)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*); - - static R DoInvoke(InvokerStorageBase* base) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), - Unwrap(invoker->p3_)); +template <typename ReturnType, typename Runnable,typename A1, typename A2, + typename A3, typename A4, typename A5> +struct InvokeHelper<false, ReturnType, Runnable, + void(A1, A2, A3, A4, A5)> { + static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, + A5 a5) { + return runnable.Run(a1, a2, a3, a4, a5); } }; -// Method: Arity 2 -> 0. -template <typename StorageType, typename R, typename T, typename X1, - typename X2> -struct Invoker3<false, StorageType, R(T::*)(X1, X2)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*); - - static R DoInvoke(InvokerStorageBase* base) { - StorageType* invoker = static_cast<StorageType*>(base); - return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), - Unwrap(invoker->p3_)); +template <typename Runnable,typename A1, typename A2, typename A3, typename A4, + typename A5> +struct InvokeHelper<false, void, Runnable, + void(A1, A2, A3, A4, A5)> { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { + runnable.Run(a1, a2, a3, a4, a5); } }; -// WeakPtr Method: Arity 2 -> 0. -template <typename StorageType, typename T, typename X1, typename X2> -struct Invoker3<true, StorageType, void(T::*)(X1, X2)> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*); - - static void DoInvoke(InvokerStorageBase* base) { - StorageType* invoker = static_cast<StorageType*>(base); - typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; - if (!weak_ptr.get()) { +template <typename Runnable, typename A1, typename A2, typename A3, + typename A4, typename A5> +struct InvokeHelper<true, void, Runnable, + void(A1, A2, A3, A4, A5)> { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { + if (!a1.get()) { return; } - (weak_ptr->*invoker->f_)(Unwrap(invoker->p2_), Unwrap(invoker->p3_)); + + runnable.Run(a1, a2, a3, a4, a5); } }; -// Function: Arity 4 -> 1. -template <typename StorageType, typename R,typename X1, typename X2, - typename X3, typename X4> -struct Invoker3<false, StorageType, R(*)(X1, X2, X3, X4)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X4>::ForwardType); - - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X4>::ForwardType x4) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), - Unwrap(invoker->p3_), x4); +template <typename ReturnType, typename Runnable,typename A1, typename A2, + typename A3, typename A4, typename A5, typename A6> +struct InvokeHelper<false, ReturnType, Runnable, + void(A1, A2, A3, A4, A5, A6)> { + static ReturnType MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, + A5 a5, A6 a6) { + return runnable.Run(a1, a2, a3, a4, a5, a6); } }; -// Method: Arity 3 -> 1. -template <typename StorageType, typename R, typename T, typename X1, - typename X2, typename X3> -struct Invoker3<false, StorageType, R(T::*)(X1, X2, X3)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X3>::ForwardType); - - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X3>::ForwardType x3) { - StorageType* invoker = static_cast<StorageType*>(base); - return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), - Unwrap(invoker->p3_), x3); +template <typename Runnable,typename A1, typename A2, typename A3, typename A4, + typename A5, typename A6> +struct InvokeHelper<false, void, Runnable, + void(A1, A2, A3, A4, A5, A6)> { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, + A6 a6) { + runnable.Run(a1, a2, a3, a4, a5, a6); } }; -// 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)> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X3>::ForwardType); - - 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()) { +template <typename Runnable, typename A1, typename A2, typename A3, + typename A4, typename A5, typename A6> +struct InvokeHelper<true, void, Runnable, + void(A1, A2, A3, A4, A5, A6)> { + static void MakeItSo(Runnable runnable, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, + A6 a6) { + if (!a1.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<false, StorageType, R(*)(X1, X2, X3, X4, X5)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X4>::ForwardType, - typename internal::ParamTraits<X5>::ForwardType); - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X4>::ForwardType x4, - typename internal::ParamTraits<X5>::ForwardType x5) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), - Unwrap(invoker->p3_), x4, x5); + runnable.Run(a1, a2, a3, a4, a5, a6); } }; -// Method: Arity 4 -> 2. -template <typename StorageType, typename R, typename T, typename X1, - typename X2, typename X3, typename X4> -struct Invoker3<false, StorageType, R(T::*)(X1, X2, X3, X4)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X3>::ForwardType, - typename internal::ParamTraits<X4>::ForwardType); +#if !defined(_MSC_VER) - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X3>::ForwardType x3, - typename internal::ParamTraits<X4>::ForwardType x4) { - StorageType* invoker = static_cast<StorageType*>(base); - return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), - Unwrap(invoker->p3_), x3, x4); - } +template <typename ReturnType, typename Runnable, typename ArgsType> +struct InvokeHelper<true, ReturnType, Runnable, ArgsType> { + // WeakCalls are only supported for functions with a void return type. + // Otherwise, the function result would be undefined if the the WeakPtr<> + // is invalidated. + COMPILE_ASSERT(is_void<ReturnType>::value, + weak_ptrs_can_only_bind_to_methods_without_return_values); }; -// 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)> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X3>::ForwardType, - typename internal::ParamTraits<X4>::ForwardType); - - 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); - } -}; +#endif -// Function: Arity 6 -> 3. -template <typename StorageType, typename R,typename X1, typename X2, - typename X3, typename X4, typename X5, typename X6> -struct Invoker3<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X4>::ForwardType, - typename internal::ParamTraits<X5>::ForwardType, - typename internal::ParamTraits<X6>::ForwardType); - - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X4>::ForwardType x4, - typename internal::ParamTraits<X5>::ForwardType x5, - typename internal::ParamTraits<X6>::ForwardType x6) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), - Unwrap(invoker->p3_), 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<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X3>::ForwardType, - typename internal::ParamTraits<X4>::ForwardType, - typename internal::ParamTraits<X5>::ForwardType); - - static R 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); - return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), - Unwrap(invoker->p3_), x3, x4, x5); - } -}; - -// 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)> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X3>::ForwardType, - typename internal::ParamTraits<X4>::ForwardType, - typename internal::ParamTraits<X5>::ForwardType); - - 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); - } -}; +// Invoker<> +// +// See description at the top of the file. +template <int NumBound, typename Storage, typename RunType> +struct Invoker; -template <bool IsWeak, typename StorageType, typename NormalizedSig> -struct Invoker4; +// Arity 0 -> 0. +template <typename StorageType, typename R> +struct Invoker<0, StorageType, R()> { + typedef R(RunType)(BindStateBase*); -// Function: Arity 4 -> 0. -template <typename StorageType, typename R,typename X1, typename X2, - typename X3, typename X4> -struct Invoker4<false, StorageType, R(*)(X1, X2, X3, X4)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*); + typedef R(UnboundRunType)(); - static R DoInvoke(InvokerStorageBase* base) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), - Unwrap(invoker->p3_), Unwrap(invoker->p4_)); - } -}; + static R Run(BindStateBase* base) { + StorageType* storage = static_cast<StorageType*>(base); -// Method: Arity 3 -> 0. -template <typename StorageType, typename R, typename T, typename X1, - typename X2, typename X3> -struct Invoker4<false, StorageType, R(T::*)(X1, X2, X3)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*); + // 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. - static R DoInvoke(InvokerStorageBase* base) { - StorageType* invoker = static_cast<StorageType*>(base); - return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), - Unwrap(invoker->p3_), Unwrap(invoker->p4_)); + return InvokeHelper<StorageType::IsWeakCall::value, R, + typename StorageType::RunnableType, + void()> + ::MakeItSo(storage->runnable_); } }; -// 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)> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*); - - 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_)); - } -}; +// Arity 1 -> 1. +template <typename StorageType, typename R,typename X1> +struct Invoker<0, StorageType, R(X1)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X1>::ForwardType); -// Function: Arity 5 -> 1. -template <typename StorageType, typename R,typename X1, typename X2, - typename X3, typename X4, typename X5> -struct Invoker4<false, StorageType, R(*)(X1, X2, X3, X4, X5)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X5>::ForwardType); + typedef R(UnboundRunType)(X1); - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X5>::ForwardType x5) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), - Unwrap(invoker->p3_), Unwrap(invoker->p4_), x5); - } -}; + static R Run(BindStateBase* base, + typename CallbackParamTraits<X1>::ForwardType x1) { + StorageType* storage = static_cast<StorageType*>(base); -// Method: Arity 4 -> 1. -template <typename StorageType, typename R, typename T, typename X1, - typename X2, typename X3, typename X4> -struct Invoker4<false, StorageType, R(T::*)(X1, X2, X3, X4)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X4>::ForwardType); + // 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. - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X4>::ForwardType x4) { - StorageType* invoker = static_cast<StorageType*>(base); - return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), - Unwrap(invoker->p3_), Unwrap(invoker->p4_), x4); + return InvokeHelper<StorageType::IsWeakCall::value, R, + typename StorageType::RunnableType, + void(typename CallbackParamTraits<X1>::ForwardType x1)> + ::MakeItSo(storage->runnable_, x1); } }; -// 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)> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X4>::ForwardType); - - 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); - } -}; +// Arity 1 -> 0. +template <typename StorageType, typename R,typename X1> +struct Invoker<1, StorageType, R(X1)> { + typedef R(RunType)(BindStateBase*); -// Function: Arity 6 -> 2. -template <typename StorageType, typename R,typename X1, typename X2, - typename X3, typename X4, typename X5, typename X6> -struct Invoker4<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X5>::ForwardType, - typename internal::ParamTraits<X6>::ForwardType); + typedef R(UnboundRunType)(); - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X5>::ForwardType x5, - typename internal::ParamTraits<X6>::ForwardType x6) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), - Unwrap(invoker->p3_), Unwrap(invoker->p4_), x5, x6); - } -}; + static R Run(BindStateBase* base) { + StorageType* storage = static_cast<StorageType*>(base); -// Method: Arity 5 -> 2. -template <typename StorageType, typename R, typename T, typename X1, - typename X2, typename X3, typename X4, typename X5> -struct Invoker4<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X4>::ForwardType, - typename internal::ParamTraits<X5>::ForwardType); + // 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; - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X4>::ForwardType x4, - typename internal::ParamTraits<X5>::ForwardType x5) { - StorageType* invoker = static_cast<StorageType*>(base); - return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), - Unwrap(invoker->p3_), Unwrap(invoker->p4_), x4, x5); + typename Bound1UnwrapTraits::ForwardType x1 = + Bound1UnwrapTraits::Unwrap(storage->p1_); + return InvokeHelper<StorageType::IsWeakCall::value, R, + typename StorageType::RunnableType, + void(typename Bound1UnwrapTraits::ForwardType)> + ::MakeItSo(storage->runnable_, x1); } }; -// 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)> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X4>::ForwardType, - typename internal::ParamTraits<X5>::ForwardType); - - 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); - } -}; +// Arity 2 -> 2. +template <typename StorageType, typename R,typename X1, typename X2> +struct Invoker<0, StorageType, R(X1, X2)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X1>::ForwardType, + typename CallbackParamTraits<X2>::ForwardType); -template <bool IsWeak, typename StorageType, typename NormalizedSig> -struct Invoker5; + typedef R(UnboundRunType)(X1, X2); -// Function: Arity 5 -> 0. -template <typename StorageType, typename R,typename X1, typename X2, - typename X3, typename X4, typename X5> -struct Invoker5<false, StorageType, R(*)(X1, X2, X3, X4, X5)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*); + static R Run(BindStateBase* base, + typename CallbackParamTraits<X1>::ForwardType x1, + typename CallbackParamTraits<X2>::ForwardType x2) { + 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. - static R DoInvoke(InvokerStorageBase* base) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), - Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_)); + return InvokeHelper<StorageType::IsWeakCall::value, R, + typename StorageType::RunnableType, + void(typename CallbackParamTraits<X1>::ForwardType x1, + typename CallbackParamTraits<X2>::ForwardType x2)> + ::MakeItSo(storage->runnable_, x1, x2); } }; -// Method: Arity 4 -> 0. -template <typename StorageType, typename R, typename T, typename X1, - typename X2, typename X3, typename X4> -struct Invoker5<false, StorageType, R(T::*)(X1, X2, X3, X4)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*); +// Arity 2 -> 1. +template <typename StorageType, typename R,typename X1, typename X2> +struct Invoker<1, StorageType, R(X1, X2)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X2>::ForwardType); - static R DoInvoke(InvokerStorageBase* base) { - StorageType* invoker = static_cast<StorageType*>(base); - return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), - Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_)); - } -}; + typedef R(UnboundRunType)(X2); -// 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)> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*); - - 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_)); - } -}; + static R Run(BindStateBase* base, + typename CallbackParamTraits<X2>::ForwardType x2) { + StorageType* storage = static_cast<StorageType*>(base); -// Function: Arity 6 -> 1. -template <typename StorageType, typename R,typename X1, typename X2, - typename X3, typename X4, typename X5, typename X6> -struct Invoker5<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X6>::ForwardType); + // 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; - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X6>::ForwardType x6) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), - Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_), x6); + 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)> + ::MakeItSo(storage->runnable_, x1, x2); } }; -// Method: Arity 5 -> 1. -template <typename StorageType, typename R, typename T, typename X1, - typename X2, typename X3, typename X4, typename X5> -struct Invoker5<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X5>::ForwardType); +// Arity 2 -> 0. +template <typename StorageType, typename R,typename X1, typename X2> +struct Invoker<2, StorageType, R(X1, X2)> { + typedef R(RunType)(BindStateBase*); - static R DoInvoke(InvokerStorageBase* base, - typename internal::ParamTraits<X5>::ForwardType x5) { - StorageType* invoker = static_cast<StorageType*>(base); - return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), - Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_), x5); - } -}; + typedef R(UnboundRunType)(); -// 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)> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<X5>::ForwardType); - - 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); + 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; + + 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)> + ::MakeItSo(storage->runnable_, x1, x2); } }; -template <bool IsWeak, typename StorageType, typename NormalizedSig> -struct Invoker6; - -// Function: Arity 6 -> 0. +// Arity 3 -> 3. template <typename StorageType, typename R,typename X1, typename X2, - typename X3, typename X4, typename X5, typename X6> -struct Invoker6<false, StorageType, R(*)(X1, X2, X3, X4, X5, X6)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*); + typename X3> +struct Invoker<0, StorageType, R(X1, X2, X3)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X1>::ForwardType, + typename CallbackParamTraits<X2>::ForwardType, + typename CallbackParamTraits<X3>::ForwardType); - static R DoInvoke(InvokerStorageBase* base) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_(Unwrap(invoker->p1_), Unwrap(invoker->p2_), - Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_), - Unwrap(invoker->p6_)); - } -}; + typedef R(UnboundRunType)(X1, X2, X3); -// Method: Arity 5 -> 0. -template <typename StorageType, typename R, typename T, typename X1, - typename X2, typename X3, typename X4, typename X5> -struct Invoker6<false, StorageType, R(T::*)(X1, X2, X3, X4, X5)> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*); + static R Run(BindStateBase* base, + typename CallbackParamTraits<X1>::ForwardType x1, + typename CallbackParamTraits<X2>::ForwardType x2, + typename CallbackParamTraits<X3>::ForwardType x3) { + StorageType* storage = static_cast<StorageType*>(base); - static R DoInvoke(InvokerStorageBase* base) { - StorageType* invoker = static_cast<StorageType*>(base); - return (Unwrap(invoker->p1_)->*invoker->f_)(Unwrap(invoker->p2_), - Unwrap(invoker->p3_), Unwrap(invoker->p4_), Unwrap(invoker->p5_), - Unwrap(invoker->p6_)); - } -}; + // 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. -// 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)> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*); - - 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_)); + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3); } }; -// BindMoreFuncN<> -// -// This set of functions help in fully binding the free parameters in a -// Callback<>. -template <typename Sig, typename P1> -void BindMoreFunc1(const base::Callback<Sig>& callback, const P1& p1) { - callback.Run(p1); -} +// Arity 3 -> 2. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3> +struct Invoker<1, StorageType, R(X1, X2, X3)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X2>::ForwardType, + typename CallbackParamTraits<X3>::ForwardType); -template <typename Sig, typename P1, typename P2> -void BindMoreFunc2(const base::Callback<Sig>& callback, const P1& p1, - const P2& p2) { - callback.Run(p1, p2); -} + typedef R(UnboundRunType)(X2, X3); -template <typename Sig, typename P1, typename P2, typename P3> -void BindMoreFunc3(const base::Callback<Sig>& callback, const P1& p1, - const P2& p2, const P3& p3) { - callback.Run(p1, p2, p3); -} + static R Run(BindStateBase* base, + typename CallbackParamTraits<X2>::ForwardType x2, + typename CallbackParamTraits<X3>::ForwardType x3) { + StorageType* storage = static_cast<StorageType*>(base); -template <typename Sig, typename P1, typename P2, typename P3, typename P4> -void BindMoreFunc4(const base::Callback<Sig>& callback, const P1& p1, - const P2& p2, const P3& p3, const P4& p4) { - callback.Run(p1, p2, p3, p4); -} + // 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; -template <typename Sig, typename P1, typename P2, typename P3, typename P4, - typename P5> -void BindMoreFunc5(const base::Callback<Sig>& callback, const P1& p1, - const P2& p2, const P3& p3, const P4& p4, const P5& p5) { - callback.Run(p1, p2, p3, p4, p5); -} + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3); + } +}; -template <typename Sig, typename P1, typename P2, typename P3, typename P4, - typename P5, typename P6> -void BindMoreFunc6(const base::Callback<Sig>& callback, const P1& p1, - const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6) { - callback.Run(p1, p2, p3, p4, p5, p6); -} +// Arity 3 -> 1. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3> +struct Invoker<2, StorageType, R(X1, X2, X3)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X3>::ForwardType); -// InvokerStorageN<> -// -// These are the actual storage classes for the Invokers. -// -// Though these types are "classes", they are being used as structs with -// all member variable public. We cannot make it a struct because it inherits -// from a class which causes a compiler warning. We cannot add a "Run()" method -// that forwards the unbound arguments because that would require we unwrap the -// Sig type like in InvokerN above to know the return type, and the arity -// of Run(). -// -// An alternate solution would be to merge InvokerN and InvokerStorageN, -// but the generated code seemed harder to read. - -template <typename Sig> -class InvokerStorage0 : public InvokerStorageBase { - public: - typedef InvokerStorage0 StorageType; - typedef FunctionTraits<Sig> TargetTraits; - typedef typename TargetTraits::IsMethod IsMethod; - typedef Sig Signature; - typedef Invoker0<false, StorageType, - typename TargetTraits::NormalizedSig> Invoker; + typedef R(UnboundRunType)(X3); + static R Run(BindStateBase* base, + typename CallbackParamTraits<X3>::ForwardType x3) { + 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; - InvokerStorage0(Sig f) - : f_(f) { + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3); } - - virtual ~InvokerStorage0() { } - - Sig f_; }; -template <typename Sig, typename P1> -class InvokerStorage1 : public InvokerStorageBase { - public: - typedef InvokerStorage1 StorageType; - typedef FunctionTraits<Sig> TargetTraits; - 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 - // disallow binding of an array as the method's target object. - COMPILE_ASSERT(IsMethod::value || - internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P1>::StorageType>::value == 0, - p1_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value, - first_bound_argument_to_method_cannot_be_array); +// Arity 3 -> 0. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3> +struct Invoker<3, StorageType, R(X1, X2, X3)> { + typedef R(RunType)(BindStateBase*); - // 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 TargetTraits::B1>::value ), - do_not_bind_functions_with_nonconst_ref); + typedef R(UnboundRunType)(); + static R Run(BindStateBase* base) { + StorageType* storage = static_cast<StorageType*>(base); - InvokerStorage1(Sig f, const P1& p1) - : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)) { - MaybeRefcount<IsMethod, P1>::AddRef(p1_); - } + // 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; - virtual ~InvokerStorage1() { - MaybeRefcount<IsMethod, P1>::Release(p1_); + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3); } - - Sig f_; - typename ParamTraits<P1>::StorageType p1_; }; -template <typename Sig, typename P1, typename P2> -class InvokerStorage2 : public InvokerStorageBase { - public: - typedef InvokerStorage2 StorageType; - typedef FunctionTraits<Sig> TargetTraits; - 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); +// Arity 4 -> 4. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4> +struct Invoker<0, StorageType, R(X1, X2, X3, X4)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X1>::ForwardType, + typename CallbackParamTraits<X2>::ForwardType, + typename CallbackParamTraits<X3>::ForwardType, + typename CallbackParamTraits<X4>::ForwardType); - // 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 - // disallow binding of an array as the method's target object. - COMPILE_ASSERT(IsMethod::value || - internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P1>::StorageType>::value == 0, - p1_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value, - first_bound_argument_to_method_cannot_be_array); - COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P2>::StorageType>::value == 0, - p2_is_refcounted_type_and_needs_scoped_refptr); + typedef R(UnboundRunType)(X1, X2, X3, X4); - // 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 TargetTraits::B1>::value || - is_non_const_reference<typename TargetTraits::B2>::value ), - do_not_bind_functions_with_nonconst_ref); + 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) { + 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. - InvokerStorage2(Sig f, const P1& p1, const P2& p2) - : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)), - p2_(static_cast<typename ParamTraits<P2>::StorageType>(p2)) { - MaybeRefcount<IsMethod, P1>::AddRef(p1_); + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4); } +}; - virtual ~InvokerStorage2() { - MaybeRefcount<IsMethod, P1>::Release(p1_); - } +// Arity 4 -> 3. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4> +struct Invoker<1, StorageType, R(X1, X2, X3, X4)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X2>::ForwardType, + typename CallbackParamTraits<X3>::ForwardType, + typename CallbackParamTraits<X4>::ForwardType); + + typedef R(UnboundRunType)(X2, X3, X4); + + static R Run(BindStateBase* base, + typename CallbackParamTraits<X2>::ForwardType x2, + typename CallbackParamTraits<X3>::ForwardType x3, + typename CallbackParamTraits<X4>::ForwardType x4) { + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4); + } +}; + +// Arity 4 -> 2. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4> +struct Invoker<2, StorageType, R(X1, X2, X3, X4)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X3>::ForwardType, + typename CallbackParamTraits<X4>::ForwardType); + + typedef R(UnboundRunType)(X3, X4); + + static R Run(BindStateBase* base, + typename CallbackParamTraits<X3>::ForwardType x3, + typename CallbackParamTraits<X4>::ForwardType x4) { + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4); + } +}; + +// Arity 4 -> 1. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4> +struct Invoker<3, StorageType, R(X1, X2, X3, X4)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X4>::ForwardType); + + typedef R(UnboundRunType)(X4); + + static R Run(BindStateBase* base, + typename CallbackParamTraits<X4>::ForwardType x4) { + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4); + } +}; + +// Arity 4 -> 0. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4> +struct Invoker<4, StorageType, R(X1, X2, X3, X4)> { + 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; + + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4); + } +}; + +// Arity 5 -> 5. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4, typename X5> +struct Invoker<0, StorageType, R(X1, X2, X3, X4, X5)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X1>::ForwardType, + typename CallbackParamTraits<X2>::ForwardType, + typename CallbackParamTraits<X3>::ForwardType, + typename CallbackParamTraits<X4>::ForwardType, + typename CallbackParamTraits<X5>::ForwardType); + + typedef R(UnboundRunType)(X1, X2, X3, X4, X5); + + 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) { + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5); + } +}; + +// Arity 5 -> 4. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4, typename X5> +struct Invoker<1, StorageType, R(X1, X2, X3, X4, X5)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X2>::ForwardType, + typename CallbackParamTraits<X3>::ForwardType, + typename CallbackParamTraits<X4>::ForwardType, + typename CallbackParamTraits<X5>::ForwardType); + + typedef R(UnboundRunType)(X2, X3, X4, X5); + + 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) { + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5); + } +}; + +// Arity 5 -> 3. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4, typename X5> +struct Invoker<2, StorageType, R(X1, X2, X3, X4, X5)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X3>::ForwardType, + typename CallbackParamTraits<X4>::ForwardType, + typename CallbackParamTraits<X5>::ForwardType); + + typedef R(UnboundRunType)(X3, X4, X5); + + static R Run(BindStateBase* base, + typename CallbackParamTraits<X3>::ForwardType x3, + typename CallbackParamTraits<X4>::ForwardType x4, + typename CallbackParamTraits<X5>::ForwardType x5) { + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5); + } +}; + +// Arity 5 -> 2. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4, typename X5> +struct Invoker<3, StorageType, R(X1, X2, X3, X4, X5)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X4>::ForwardType, + typename CallbackParamTraits<X5>::ForwardType); + + typedef R(UnboundRunType)(X4, X5); + + static R Run(BindStateBase* base, + typename CallbackParamTraits<X4>::ForwardType x4, + typename CallbackParamTraits<X5>::ForwardType x5) { + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5); + } +}; + +// Arity 5 -> 1. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4, typename X5> +struct Invoker<4, StorageType, R(X1, X2, X3, X4, X5)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X5>::ForwardType); + + typedef R(UnboundRunType)(X5); + + static R Run(BindStateBase* base, + typename CallbackParamTraits<X5>::ForwardType x5) { + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5); + } +}; + +// Arity 5 -> 0. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4, typename X5> +struct Invoker<5, StorageType, R(X1, X2, X3, X4, X5)> { + 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; + + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5); + } +}; + +// Arity 6 -> 6. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4, typename X5, typename X6> +struct Invoker<0, StorageType, R(X1, X2, X3, X4, X5, X6)> { + 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); + + typedef R(UnboundRunType)(X1, X2, X3, X4, X5, X6); + + 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) { + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6); + } +}; + +// Arity 6 -> 5. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4, typename X5, typename X6> +struct Invoker<1, StorageType, R(X1, X2, X3, X4, X5, X6)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X2>::ForwardType, + typename CallbackParamTraits<X3>::ForwardType, + typename CallbackParamTraits<X4>::ForwardType, + typename CallbackParamTraits<X5>::ForwardType, + typename CallbackParamTraits<X6>::ForwardType); + + typedef R(UnboundRunType)(X2, X3, X4, X5, X6); + + 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) { + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6); + } +}; + +// Arity 6 -> 4. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4, typename X5, typename X6> +struct Invoker<2, StorageType, R(X1, X2, X3, X4, X5, X6)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X3>::ForwardType, + typename CallbackParamTraits<X4>::ForwardType, + typename CallbackParamTraits<X5>::ForwardType, + typename CallbackParamTraits<X6>::ForwardType); + + typedef R(UnboundRunType)(X3, X4, X5, X6); + + 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) { + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6); + } +}; + +// Arity 6 -> 3. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4, typename X5, typename X6> +struct Invoker<3, StorageType, R(X1, X2, X3, X4, X5, X6)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X4>::ForwardType, + typename CallbackParamTraits<X5>::ForwardType, + typename CallbackParamTraits<X6>::ForwardType); + + typedef R(UnboundRunType)(X4, X5, X6); + + static R Run(BindStateBase* base, + typename CallbackParamTraits<X4>::ForwardType x4, + typename CallbackParamTraits<X5>::ForwardType x5, + typename CallbackParamTraits<X6>::ForwardType x6) { + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6); + } +}; + +// Arity 6 -> 2. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4, typename X5, typename X6> +struct Invoker<4, StorageType, R(X1, X2, X3, X4, X5, X6)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X5>::ForwardType, + typename CallbackParamTraits<X6>::ForwardType); + + typedef R(UnboundRunType)(X5, X6); + + static R Run(BindStateBase* base, + typename CallbackParamTraits<X5>::ForwardType x5, + typename CallbackParamTraits<X6>::ForwardType x6) { + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6); + } +}; + +// Arity 6 -> 1. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4, typename X5, typename X6> +struct Invoker<5, StorageType, R(X1, X2, X3, X4, X5, X6)> { + typedef R(RunType)(BindStateBase*, + typename CallbackParamTraits<X6>::ForwardType); + + typedef R(UnboundRunType)(X6); + + static R Run(BindStateBase* base, + typename CallbackParamTraits<X6>::ForwardType x6) { + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6); + } +}; + +// Arity 6 -> 0. +template <typename StorageType, typename R,typename X1, typename X2, + typename X3, typename X4, typename X5, typename X6> +struct Invoker<6, StorageType, R(X1, X2, X3, X4, X5, X6)> { + 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; + + 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)> + ::MakeItSo(storage->runnable_, x1, x2, x3, x4, x5, x6); + } +}; + + +// BindState<> +// +// This stores all the state passed into Bind() and is also where most +// of the template resolution magic occurs. +// +// Runnable is the functor we are binding arguments to. +// RunType is type of the Run() function that the Invoker<> should use. +// Normally, this is the same as the RunType of the Runnable, but it can +// be different if an adapter like IgnoreResult() has been used. +// +// BoundArgsType contains the storage type for all the bound arguments by +// (ab)using a function type. +template <typename Runnable, typename RunType, typename BoundArgsType> +struct BindState; - Sig f_; - typename ParamTraits<P1>::StorageType p1_; - typename ParamTraits<P2>::StorageType p2_; -}; +template <typename Runnable, typename RunType> +struct BindState<Runnable, RunType, void()> : public BindStateBase { + typedef Runnable RunnableType; + typedef false_type IsWeakCall; + typedef Invoker<0, BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + explicit BindState(const Runnable& runnable) + : runnable_(runnable) { + } -template <typename Sig, typename P1, typename P2, typename P3> -class InvokerStorage3 : public InvokerStorageBase { - public: - typedef InvokerStorage3 StorageType; - typedef FunctionTraits<Sig> TargetTraits; - 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); + virtual ~BindState() { } - // 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 - // disallow binding of an array as the method's target object. - COMPILE_ASSERT(IsMethod::value || - internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P1>::StorageType>::value == 0, - p1_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value, - first_bound_argument_to_method_cannot_be_array); - COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P2>::StorageType>::value == 0, - p2_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P3>::StorageType>::value == 0, - p3_is_refcounted_type_and_needs_scoped_refptr); - - // 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 TargetTraits::B1>::value || - is_non_const_reference<typename TargetTraits::B2>::value || - is_non_const_reference<typename TargetTraits::B3>::value ), - do_not_bind_functions_with_nonconst_ref); - - - InvokerStorage3(Sig f, const P1& p1, const P2& p2, const P3& p3) - : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)), - p2_(static_cast<typename ParamTraits<P2>::StorageType>(p2)), - p3_(static_cast<typename ParamTraits<P3>::StorageType>(p3)) { - MaybeRefcount<IsMethod, P1>::AddRef(p1_); - } - - virtual ~InvokerStorage3() { - MaybeRefcount<IsMethod, P1>::Release(p1_); - } - - Sig f_; - typename ParamTraits<P1>::StorageType p1_; - typename ParamTraits<P2>::StorageType p2_; - typename ParamTraits<P3>::StorageType p3_; -}; - -template <typename Sig, typename P1, typename P2, typename P3, typename P4> -class InvokerStorage4 : public InvokerStorageBase { - public: - typedef InvokerStorage4 StorageType; - typedef FunctionTraits<Sig> TargetTraits; - 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); + RunnableType runnable_; +}; + +template <typename Runnable, typename RunType, typename P1> +struct BindState<Runnable, RunType, void(P1)> : public BindStateBase { + typedef Runnable RunnableType; + typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall; + typedef Invoker<1, BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; - // 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 - // disallow binding of an array as the method's target object. - COMPILE_ASSERT(IsMethod::value || - internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P1>::StorageType>::value == 0, - p1_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value, - first_bound_argument_to_method_cannot_be_array); - COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P2>::StorageType>::value == 0, - p2_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P3>::StorageType>::value == 0, - p3_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P4>::StorageType>::value == 0, - p4_is_refcounted_type_and_needs_scoped_refptr); - - // 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 TargetTraits::B1>::value || - is_non_const_reference<typename TargetTraits::B2>::value || - is_non_const_reference<typename TargetTraits::B3>::value || - is_non_const_reference<typename TargetTraits::B4>::value ), - do_not_bind_functions_with_nonconst_ref); - - - InvokerStorage4(Sig f, const P1& p1, const P2& p2, const P3& p3, const P4& p4) - : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)), - p2_(static_cast<typename ParamTraits<P2>::StorageType>(p2)), - p3_(static_cast<typename ParamTraits<P3>::StorageType>(p3)), - p4_(static_cast<typename ParamTraits<P4>::StorageType>(p4)) { - MaybeRefcount<IsMethod, P1>::AddRef(p1_); - } - - virtual ~InvokerStorage4() { - MaybeRefcount<IsMethod, P1>::Release(p1_); - } - - Sig f_; - typename ParamTraits<P1>::StorageType p1_; - typename ParamTraits<P2>::StorageType p2_; - typename ParamTraits<P3>::StorageType p3_; - typename ParamTraits<P4>::StorageType p4_; -}; - -template <typename Sig, typename P1, typename P2, typename P3, typename P4, - typename P5> -class InvokerStorage5 : public InvokerStorageBase { - public: - typedef InvokerStorage5 StorageType; - typedef FunctionTraits<Sig> TargetTraits; - 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); + // Convenience typedefs for bound argument types. + typedef UnwrapTraits<P1> Bound1UnwrapTraits; - // 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 - // disallow binding of an array as the method's target object. - COMPILE_ASSERT(IsMethod::value || - internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P1>::StorageType>::value == 0, - p1_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value, - first_bound_argument_to_method_cannot_be_array); - COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P2>::StorageType>::value == 0, - p2_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P3>::StorageType>::value == 0, - p3_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P4>::StorageType>::value == 0, - p4_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P5>::StorageType>::value == 0, - p5_is_refcounted_type_and_needs_scoped_refptr); - - // 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 TargetTraits::B1>::value || - is_non_const_reference<typename TargetTraits::B2>::value || - is_non_const_reference<typename TargetTraits::B3>::value || - is_non_const_reference<typename TargetTraits::B4>::value || - is_non_const_reference<typename TargetTraits::B5>::value ), - do_not_bind_functions_with_nonconst_ref); - - - InvokerStorage5(Sig f, const P1& p1, const P2& p2, const P3& p3, - const P4& p4, const P5& p5) - : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)), - p2_(static_cast<typename ParamTraits<P2>::StorageType>(p2)), - p3_(static_cast<typename ParamTraits<P3>::StorageType>(p3)), - p4_(static_cast<typename ParamTraits<P4>::StorageType>(p4)), - p5_(static_cast<typename ParamTraits<P5>::StorageType>(p5)) { - MaybeRefcount<IsMethod, P1>::AddRef(p1_); + BindState(const Runnable& runnable, const P1& p1) + : runnable_(runnable), + p1_(p1) { + MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_); } - virtual ~InvokerStorage5() { - MaybeRefcount<IsMethod, P1>::Release(p1_); - } + virtual ~BindState() { MaybeRefcount<HasIsMethodTag<Runnable>::value, + P1>::Release(p1_); } - Sig f_; - typename ParamTraits<P1>::StorageType p1_; - typename ParamTraits<P2>::StorageType p2_; - typename ParamTraits<P3>::StorageType p3_; - typename ParamTraits<P4>::StorageType p4_; - typename ParamTraits<P5>::StorageType p5_; -}; + RunnableType runnable_; + P1 p1_; +}; -template <typename Sig, typename P1, typename P2, typename P3, typename P4, - typename P5, typename P6> -class InvokerStorage6 : public InvokerStorageBase { - public: - typedef InvokerStorage6 StorageType; - typedef FunctionTraits<Sig> TargetTraits; - 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); +template <typename Runnable, typename RunType, typename P1, typename P2> +struct BindState<Runnable, RunType, void(P1, P2)> : public BindStateBase { + typedef Runnable RunnableType; + typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall; + typedef Invoker<2, BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + + // Convenience typedefs for bound argument types. + typedef UnwrapTraits<P1> Bound1UnwrapTraits; + typedef UnwrapTraits<P2> Bound2UnwrapTraits; + + BindState(const Runnable& runnable, const P1& p1, const P2& p2) + : runnable_(runnable), + p1_(p1), + p2_(p2) { + MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_); + } + + virtual ~BindState() { MaybeRefcount<HasIsMethodTag<Runnable>::value, + P1>::Release(p1_); } + + RunnableType runnable_; + P1 p1_; + P2 p2_; +}; + +template <typename Runnable, typename RunType, typename P1, typename P2, + typename P3> +struct BindState<Runnable, RunType, void(P1, P2, P3)> : public BindStateBase { + typedef Runnable RunnableType; + typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall; + typedef Invoker<3, 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; + + BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3) + : runnable_(runnable), + p1_(p1), + p2_(p2), + p3_(p3) { + MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_); + } + + virtual ~BindState() { MaybeRefcount<HasIsMethodTag<Runnable>::value, + P1>::Release(p1_); } + + RunnableType runnable_; + P1 p1_; + P2 p2_; + P3 p3_; +}; + +template <typename Runnable, typename RunType, typename P1, typename P2, + typename P3, typename P4> +struct BindState<Runnable, RunType, void(P1, P2, P3, + P4)> : public BindStateBase { + typedef Runnable RunnableType; + typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall; + typedef Invoker<4, 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; - // 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 - // disallow binding of an array as the method's target object. - COMPILE_ASSERT(IsMethod::value || - internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P1>::StorageType>::value == 0, - p1_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value, - first_bound_argument_to_method_cannot_be_array); - COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P2>::StorageType>::value == 0, - p2_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P3>::StorageType>::value == 0, - p3_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P4>::StorageType>::value == 0, - p4_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P5>::StorageType>::value == 0, - p5_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P6>::StorageType>::value == 0, - p6_is_refcounted_type_and_needs_scoped_refptr); - - // 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 TargetTraits::B1>::value || - is_non_const_reference<typename TargetTraits::B2>::value || - is_non_const_reference<typename TargetTraits::B3>::value || - is_non_const_reference<typename TargetTraits::B4>::value || - is_non_const_reference<typename TargetTraits::B5>::value || - is_non_const_reference<typename TargetTraits::B6>::value ), - do_not_bind_functions_with_nonconst_ref); - - - InvokerStorage6(Sig f, const P1& p1, const P2& p2, const P3& p3, + BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3, + const P4& p4) + : runnable_(runnable), + p1_(p1), + p2_(p2), + p3_(p3), + p4_(p4) { + 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_; +}; + +template <typename Runnable, typename RunType, typename P1, typename P2, + typename P3, typename P4, typename P5> +struct BindState<Runnable, RunType, void(P1, P2, P3, P4, + P5)> : public BindStateBase { + typedef Runnable RunnableType; + typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall; + typedef Invoker<5, 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; + + BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3, + const P4& p4, const P5& p5) + : runnable_(runnable), + p1_(p1), + p2_(p2), + p3_(p3), + p4_(p4), + p5_(p5) { + 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_; +}; + +template <typename Runnable, typename RunType, typename P1, typename P2, + typename P3, typename P4, typename P5, typename P6> +struct BindState<Runnable, RunType, void(P1, P2, P3, P4, P5, + P6)> : public BindStateBase { + typedef Runnable RunnableType; + typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall; + typedef Invoker<6, 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; + + BindState(const Runnable& runnable, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6) - : f_(f), p1_(static_cast<typename ParamTraits<P1>::StorageType>(p1)), - p2_(static_cast<typename ParamTraits<P2>::StorageType>(p2)), - p3_(static_cast<typename ParamTraits<P3>::StorageType>(p3)), - p4_(static_cast<typename ParamTraits<P4>::StorageType>(p4)), - p5_(static_cast<typename ParamTraits<P5>::StorageType>(p5)), - p6_(static_cast<typename ParamTraits<P6>::StorageType>(p6)) { - MaybeRefcount<IsMethod, P1>::AddRef(p1_); - } - - virtual ~InvokerStorage6() { - MaybeRefcount<IsMethod, P1>::Release(p1_); - } - - Sig f_; - typename ParamTraits<P1>::StorageType p1_; - typename ParamTraits<P2>::StorageType p2_; - typename ParamTraits<P3>::StorageType p3_; - typename ParamTraits<P4>::StorageType p4_; - typename ParamTraits<P5>::StorageType p5_; - typename ParamTraits<P6>::StorageType p6_; + : runnable_(runnable), + p1_(p1), + p2_(p2), + p3_(p3), + p4_(p4), + p5_(p5), + p6_(p6) { + 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_; }; } // namespace internal diff --git a/base/bind_internal.h.pump b/base/bind_internal.h.pump index 429e13f..1192974 100644 --- a/base/bind_internal.h.pump +++ b/base/bind_internal.h.pump @@ -5,7 +5,14 @@ $$ $$ 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 +$range ARITY 0..MAX_ARITY // Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -29,371 +36,463 @@ $var MAX_ARITY = 6 namespace base { namespace internal { -// The method by which a function is invoked is determined by 3 different -// dimensions: +// CONCEPTS: +// Runnable -- A type (really a type class) that has a single Run() method +// and a RunType typedef that corresponds to the type of Run(). +// A Runnable can declare that it should treated like a method +// call by including a typedef named IsMethod. The value of +// this typedef is NOT inspected, only the existence. When a +// Runnable declares itself a method, Bind() will enforce special +// refcounting + WeakPtr handling semantics for the first +// parameter which is expected to be an object. +// Functor -- A copyable type representing something that should be called. +// All function pointers, Callback<>, and Runnables are functors +// even if the invocation syntax differs. +// RunType -- A function type (as opposed to function _pointer_ type) for +// a Run() function. Usually just a convenience typedef. +// (Bound)ArgsType -- A function type that is being (ab)used to store the +// types of set of arguments. The "return" type is always +// void here. We use this hack so that we do not need +// a new type name for each arity of type. (eg., +// BindState1, BindState2). This makes forward +// declarations and friending much much easier. // -// 1) The type of function (normal or method). -// 2) The arity of the function. -// 3) The number of bound parameters. +// Types: +// RunnableAdapter<> -- Wraps the various "function" pointer types into an +// object that adheres to the Runnable interface. +// There are |3*ARITY| RunnableAdapter types. +// FunctionTraits<> -- Type traits that unwrap a function signature into a +// a set of easier to use typedefs. Used mainly for +// compile time asserts. +// There are |ARITY| FunctionTraits types. +// ForceVoidReturn<> -- Helper class for translating function signatures to +// equivalent forms with a "void" return type. +// There are |ARITY| ForceVoidReturn types. +// FunctorTraits<> -- Type traits used determine the correct RunType and +// RunnableType for a Functor. This is where function +// signature adapters are applied. +// There are |ARITY| ForceVoidReturn types. +// MakeRunnable<> -- Takes a Functor and returns an object in the Runnable +// type class that represents the underlying Functor. +// There are |O(1)| MakeRunnable types. +// InvokeHelper<> -- Take a Runnable + arguments and actully invokes it. +// Handle the differing syntaxes needed for WeakPtr<> support, +// and for ignoring return values. This is separate from +// Invoker to avoid creating multiple version of Invoker<> +// which grows at O(n^2) with the arity. +// There are |k*ARITY| InvokeHelper types. +// Invoker<> -- Unwraps the curried parameters and executes the Runnable. +// There are |(ARITY^2 + ARITY)/2| Invoketypes. +// BindState<> -- Stores the curried parameters, and is the main entry point +// into the Bind() system, doing most of the type resolution. +// There are ARITY BindState types. + + +// RunnableAdapter<> // -// The templates below handle the determination of each of these dimensions. -// In brief: -// -// FunctionTraits<> -- Provides a normalied signature, and other traits. -// InvokerN<> -- Provides a DoInvoke() function that actually executes -// 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 RunnableAdapter<> templates provide a uniform interface for invoking +// a function pointer, method pointer, or const method pointer. The adapter +// exposes a Run() method with an appropriate signature. Using this wrapper +// allows for writing code that supports all three pointer types without +// undue repetition. Without it, a lot of code would need to be repeated 3 +// times. // -// The FunctionTraits<> template determines the type of function, and also -// creates a NormalizedType used to select the InvokerN classes. It turns out -// that syntactically, you only really have 2 variations when invoking a -// funciton pointer: normal, and method. One is invoked func_ptr(arg1). The -// other is invoked (*obj_->method_ptr(arg1)). +// For method pointers and const method pointers the first argument to Run() +// is considered to be the received of the method. This is similar to STL's +// mem_fun(). // -// However, in the type system, there are many more distinctions. In standard -// C++, there's all variations of const, and volatile on the function pointer. -// In Windows, there are additional calling conventions (eg., __stdcall, -// __fastcall, etc.). FunctionTraits<> handles categorizing each of these into -// a normalized signature. +// This class also exposes a RunType typedef that is the function type of the +// Run() function. // -// Having a NormalizedSignature signature, reduces the combinatoric -// complexity of defintions for the InvokerN<> later. Even though there are -// only 2 syntactic variations on invoking a function, without normalizing the -// signature, there would need to be one specialization of InvokerN for each -// unique (function_type, bound_arg, unbound_args) tuple in order to match all -// function signatures. -// -// By normalizing the function signature, we reduce function_type to exactly 2. +// If and only if the wrapper contains a method or const method pointer, an +// IsMethod typedef is exposed. The existence of this typedef (NOT the value) +// marks that the wrapper should be considered a method wrapper. -template <typename Sig> -struct FunctionTraits; +template <typename Functor> +class RunnableAdapter; -$range ARITY 0..MAX_ARITY $for ARITY [[ $range ARG 1..ARITY // Function: Arity $(ARITY). template <typename R[[]] -$if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> -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. +$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]> +class RunnableAdapter<R(*)($for ARG , [[A$(ARG)]])> { + public: + typedef R (RunType)($for ARG , [[A$(ARG)]]); -$for ARG [[ - typedef X$(ARG) B$(ARG); + explicit RunnableAdapter(R(*function)($for ARG , [[A$(ARG)]])) + : function_(function) { + } -]] $$ for ARG -]] $$ if ARITY > 0 + R Run($for ARG , [[typename CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) { + return function_($for ARG , [[a$(ARG)]]); + } + private: + R (*function_)($for ARG , [[A$(ARG)]]); }; // Method: Arity $(ARITY). template <typename R, typename T[[]] -$if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> -struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]])> { - typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]); +$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]> +class RunnableAdapter<R(T::*)($for ARG , [[A$(ARG)]])> { + public: + typedef R (RunType)(T*[[]] +$if ARITY > 0[[, ]] $for ARG , [[A$(ARG)]]); typedef true_type IsMethod; - typedef R Return; - - // Target type for each bound parameter. - typedef T B1; - -$for ARG [[ - typedef X$(ARG) B$(ARG + 1); + explicit RunnableAdapter(R(T::*method)($for ARG , [[A$(ARG)]])) + : method_(method) { + } -]] $$ for ARG + R Run(T* object[[]] +$if ARITY > 0[[, ]] $for ARG, [[typename CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) { + return (object->*method_)($for ARG , [[a$(ARG)]]); + } + private: + R (T::*method_)($for ARG , [[A$(ARG)]]); }; // Const Method: Arity $(ARITY). template <typename R, typename T[[]] -$if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> -struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]]) const> { - typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]); +$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]> +class RunnableAdapter<R(T::*)($for ARG , [[A$(ARG)]]) const> { + public: + typedef R (RunType)(const T*[[]] +$if ARITY > 0[[, ]] $for ARG , [[A$(ARG)]]); typedef true_type IsMethod; - typedef R Return; + explicit RunnableAdapter(R(T::*method)($for ARG , [[A$(ARG)]]) const) + : method_(method) { + } + + R Run(const T* object[[]] +$if ARITY > 0[[, ]] $for ARG, [[typename CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) { + return (object->*method_)($for ARG , [[a$(ARG)]]); + } + + private: + R (T::*method_)($for ARG , [[A$(ARG)]]) const; +}; + +]] $$ for ARITY + - // Target type for each bound parameter. - typedef T B1; +// FunctionTraits<> +// +// Breaks a function signature apart into typedefs for easier introspection. +template <typename Sig> +struct FunctionTraits; +$for ARITY [[ +$range ARG 1..ARITY + +template <typename R[[]] +$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]> +struct FunctionTraits<R($for ARG , [[A$(ARG)]])> { + typedef R ReturnType; $for ARG [[ - typedef X$(ARG) B$(ARG + 1); -]] $$ for ARG + typedef A$(ARG) A$(ARG)Type; +]] }; -]] $$for ARITY +]] -// InvokerN<> -// -// The InvokerN templates contain a static DoInvoke() function that is the key -// to implementing type erasure in the Callback() classes. -// -// DoInvoke() is a static function with a fixed signature that is independent -// of StorageType; its first argument is a pointer to the non-templated common -// baseclass of StorageType. This lets us store pointer to DoInvoke() in a -// function pointer that has knowledge of the specific StorageType, and thus -// no knowledge of the bound function and bound parameter types. + +// ForceVoidReturn<> // -// As long as we ensure that DoInvoke() is only used with pointers there were -// upcasted from the correct StorageType, we can be sure that execution is -// safe. +// Set of templates that support forcing the function return type to void. +template <typename Sig> +struct ForceVoidReturn; + +$for ARITY [[ +$range ARG 1..ARITY + +template <typename R[[]] +$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]> +struct ForceVoidReturn<R($for ARG , [[A$(ARG)]])> { + typedef void(RunType)($for ARG , [[A$(ARG)]]); +}; + +]] $$ for ARITY + + +// FunctorTraits<> // -// The InvokerN templates are the only point that knows the number of bound -// and unbound arguments. This is intentional because it allows the other -// templates classes in the system to only have as many specializations as -// the max arity of function we wish to support. +// See description at top of file. +template <typename T> +struct FunctorTraits { + typedef RunnableAdapter<T> RunnableType; + typedef typename RunnableType::RunType RunType; +}; -$range BOUND 0..MAX_ARITY -$for BOUND [[ +template <typename T> +struct FunctorTraits<IgnoreResultHelper<T> > { + typedef typename FunctorTraits<T>::RunnableType RunnableType; + typedef typename ForceVoidReturn< + typename RunnableType::RunType>::RunType RunType; +}; -template <bool IsWeak, typename StorageType, typename NormalizedSig> -struct Invoker$(BOUND); +template <typename T> +struct FunctorTraits<Callback<T> > { + typedef Callback<T> RunnableType; + typedef typename Callback<T>::RunType RunType; +}; -$range ARITY 0..MAX_ARITY -$for ARITY [[ -$var UNBOUND = ARITY - BOUND -$if UNBOUND >= 0 [[ +// MakeRunnable<> +// +// Converts a passed in functor to a RunnableType using type inference. -$$ Variables for function traits generation. -$range ARG 1..ARITY -$range BOUND_ARG 1..BOUND -$range UNBOUND_ARG (ARITY - UNBOUND + 1)..ARITY +template <typename T> +typename FunctorTraits<T>::RunnableType MakeRunnable(const T& t) { + return RunnableAdapter<T>(t); +} -$$ Variables for method traits generation. We are always short one arity since -$$ the first bound parameter is the object. -$var M_ARITY = ARITY - 1 -$range M_ARG 1..M_ARITY -$range M_BOUND_ARG 2..BOUND -$range M_UNBOUND_ARG (M_ARITY - UNBOUND + 1)..M_ARITY +template <typename T> +typename FunctorTraits<T>::RunnableType +MakeRunnable(const IgnoreResultHelper<T>& t) { + return MakeRunnable(t.functor_); +} -// Function: Arity $(ARITY) -> $(UNBOUND). -template <typename StorageType, typename R[[]] -$if ARITY > 0 [[,]][[]] -$for ARG , [[typename X$(ARG)]]> -struct Invoker$(BOUND)<false, StorageType, R(*)($for ARG , [[X$(ARG)]])> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*[[]] -$if UNBOUND != 0 [[, ]] -$for UNBOUND_ARG , [[typename internal::ParamTraits<X$(UNBOUND_ARG)>::ForwardType]]); +template <typename T> +const typename FunctorTraits<Callback<T> >::RunnableType& +MakeRunnable(const Callback<T>& t) { + return t; +} - static R DoInvoke(InvokerStorageBase* base[[]] -$if UNBOUND != 0 [[, ]][[]] -$for UNBOUND_ARG , [[typename internal::ParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG)]]) { - StorageType* invoker = static_cast<StorageType*>(base); - return invoker->f_($for BOUND_ARG , [[Unwrap(invoker->p$(BOUND_ARG)_)]][[]] -$$ Add comma if there are both boudn and unbound args. -$if UNBOUND > 0 [[$if BOUND > 0 [[, ]]]][[]] -$for UNBOUND_ARG , [[x$(UNBOUND_ARG)]]); + +// InvokeHelper<> +// +// There are 3 logical InvokeHelper<> specializations: normal, void-return, +// WeakCalls. +// +// The normal type just calls the underlying runnable. +// +// We need a InvokeHelper to handle void return types in order to support +// IgnoreResult(). Normally, if the Runnable's RunType had a void return, +// the template system would just accept "return functor.Run()" ignoring +// the fact that a void function is being used with return. This piece of +// sugar breaks though when the Runnable's RunType is not void. Thus, we +// need a partial specialization to change the syntax to drop the "return" +// from the invocation call. +// +// WeakCalls similarly need special syntax that is applied to the first +// argument to check if they should no-op themselves. +template <bool IsWeakCall, typename ReturnType, typename Runnable, + typename ArgsType> +struct InvokeHelper; + +$for ARITY [[ +$range ARG 1..ARITY + +template <typename ReturnType, typename Runnable[[]] +$if ARITY > 0 [[,]] $for ARG , [[typename A$(ARG)]]> +struct InvokeHelper<false, ReturnType, Runnable, + void($for ARG , [[A$(ARG)]])> { + static ReturnType MakeItSo(Runnable runnable[[]] +$if ARITY > 0[[, ]] $for ARG , [[A$(ARG) a$(ARG)]]) { + return runnable.Run($for ARG , [[a$(ARG)]]); } }; -$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)<false, StorageType, R(T::*)($for M_ARG , [[X$(M_ARG)]])> { - typedef R(*DoInvokeType)( - internal::InvokerStorageBase*[[]] -$if UNBOUND != 0 [[, ]] -$for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::ForwardType]]); - - static R 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); - return (Unwrap(invoker->p1_)->*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)]]); +template <typename Runnable[[]] +$if ARITY > 0 [[,]] $for ARG , [[typename A$(ARG)]]> +struct InvokeHelper<false, void, Runnable, + void($for ARG , [[A$(ARG)]])> { + static void MakeItSo(Runnable runnable[[]] +$if ARITY > 0[[, ]] $for ARG , [[A$(ARG) a$(ARG)]]) { + runnable.Run($for ARG , [[a$(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)]])> { - typedef void(*DoInvokeType)( - internal::InvokerStorageBase*[[]] -$if UNBOUND != 0 [[, ]] -$for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::ForwardType]]); - - 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()) { +$if ARITY > 0 [[ + +template <typename Runnable[[]], $for ARG , [[typename A$(ARG)]]> +struct InvokeHelper<true, void, Runnable, + void($for ARG , [[A$(ARG)]])> { + static void MakeItSo(Runnable runnable[[]] +$if ARITY > 0[[, ]] $for ARG , [[A$(ARG) a$(ARG)]]) { + if (!a1.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)]]); + + runnable.Run($for ARG , [[a$(ARG)]]); } }; -]] $$ if BOUND +]] -]] $$ if UNBOUND -]] $$ for ARITY -]] $$ for BOUND +]] $$ for ARITY -// BindMoreFuncN<> -// -// This set of functions help in fully binding the free parameters in a -// Callback<>. -$for BOUND [[ -$range BOUND_ARG 1..BOUND -$if BOUND != 0 [[ +#if !defined(_MSC_VER) -template <typename Sig, $for BOUND_ARG , [[typename P$(BOUND_ARG)]]> -void BindMoreFunc$(BOUND)(const base::Callback<Sig>& callback, [[]] -$for BOUND_ARG , [[const P$(BOUND_ARG)& p$(BOUND_ARG)]]) { - callback.Run($for BOUND_ARG , [[p$(BOUND_ARG)]]); -} +template <typename ReturnType, typename Runnable, typename ArgsType> +struct InvokeHelper<true, ReturnType, Runnable, ArgsType> { + // WeakCalls are only supported for functions with a void return type. + // Otherwise, the function result would be undefined if the the WeakPtr<> + // is invalidated. + COMPILE_ASSERT(is_void<ReturnType>::value, + weak_ptrs_can_only_bind_to_methods_without_return_values); +}; -]] $$ if BOUND -]] $$ for BOUND +#endif -// InvokerStorageN<> -// -// These are the actual storage classes for the Invokers. -// -// Though these types are "classes", they are being used as structs with -// all member variable public. We cannot make it a struct because it inherits -// from a class which causes a compiler warning. We cannot add a "Run()" method -// that forwards the unbound arguments because that would require we unwrap the -// Sig type like in InvokerN above to know the return type, and the arity -// of Run(). +// Invoker<> // -// An alternate solution would be to merge InvokerN and InvokerStorageN, -// but the generated code seemed harder to read. +// See description at the top of the file. +template <int NumBound, typename Storage, typename RunType> +struct Invoker; +$for ARITY [[ + +$$ Number of bound arguments. +$range BOUND 0..ARITY $for BOUND [[ + +$var UNBOUND = ARITY - BOUND +$range ARG 1..ARITY $range BOUND_ARG 1..BOUND +$range UNBOUND_ARG (ARITY - UNBOUND + 1)..ARITY -template <typename Sig[[]] -$if BOUND > 0 [[, ]] -$for BOUND_ARG , [[typename P$(BOUND_ARG)]]> -class InvokerStorage$(BOUND) : public InvokerStorageBase { - public: - typedef InvokerStorage$(BOUND) StorageType; - typedef FunctionTraits<Sig> TargetTraits; - typedef typename TargetTraits::IsMethod IsMethod; - typedef Sig Signature; +// Arity $(ARITY) -> $(UNBOUND). +template <typename StorageType, typename R[[]] +$if ARITY > 0 [[,]][[]] +$for ARG , [[typename X$(ARG)]]> +struct Invoker<$(BOUND), StorageType, R($for ARG , [[X$(ARG)]])> { + typedef R(RunType)(BindStateBase*[[]] +$if UNBOUND != 0 [[, ]] +$for UNBOUND_ARG , [[typename CallbackParamTraits<X$(UNBOUND_ARG)>::ForwardType]]); -$for BOUND_ARG [[ - typedef ParamTraits<P$(BOUND_ARG)> P$(BOUND_ARG)Traits; + typedef R(UnboundRunType)($for UNBOUND_ARG , [[X$(UNBOUND_ARG)]]); + static R Run(BindStateBase* base[[]] +$if UNBOUND != 0 [[, ]][[]] +$for UNBOUND_ARG , [[ +typename CallbackParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG) +]][[]] +) { + 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. +$for BOUND_ARG +[[ + + typedef typename StorageType::Bound$(BOUND_ARG)UnwrapTraits Bound$(BOUND_ARG)UnwrapTraits; ]] -$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 +[[ + + typename Bound$(BOUND_ARG)UnwrapTraits::ForwardType x$(BOUND_ARG) = + Bound$(BOUND_ARG)UnwrapTraits::Unwrap(storage->p$(BOUND_ARG)_); ]] + return InvokeHelper<StorageType::IsWeakCall::value, R, + typename StorageType::RunnableType, + void( +$for BOUND_ARG , [[ +typename Bound$(BOUND_ARG)UnwrapTraits::ForwardType +]] -$for BOUND_ARG [[ -$if BOUND_ARG == 1 [[ +$if UNBOUND > 0 [[$if BOUND > 0 [[, ]]]][[]] - // 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 - // disallow binding of an array as the method's target object. - COMPILE_ASSERT(IsMethod::value || - internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P$(BOUND_ARG)>::StorageType>::value == 0, - p$(BOUND_ARG)_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!IsMethod::value || !is_array<P$(BOUND_ARG)>::value, - first_bound_argument_to_method_cannot_be_array); -]] $else [[ +$for UNBOUND_ARG , [[ +typename CallbackParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG) +]] +)> + ::MakeItSo(storage->runnable_ +$if ARITY > 0[[, ]] $for ARG , [[x$(ARG)]]); + } +}; + +]] $$ for BOUND +]] $$ for ARITY - COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr< - typename ParamTraits<P$(BOUND_ARG)>::StorageType>::value == 0, - p$(BOUND_ARG)_is_refcounted_type_and_needs_scoped_refptr); -]] $$ $if BOUND_ARG -]] $$ $for BOUND_ARG +// BindState<> +// +// This stores all the state passed into Bind() and is also where most +// of the template resolution magic occurs. +// +// Runnable is the functor we are binding arguments to. +// RunType is type of the Run() function that the Invoker<> should use. +// Normally, this is the same as the RunType of the Runnable, but it can +// be different if an adapter like IgnoreResult() has been used. +// +// BoundArgsType contains the storage type for all the bound arguments by +// (ab)using a function type. +template <typename Runnable, typename RunType, typename BoundArgsType> +struct BindState; -$if BOUND > 0 [[ +$for ARITY [[ +$range ARG 1..ARITY - // 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( - !($for BOUND_ARG || [[ is_non_const_reference<typename TargetTraits::B$(BOUND_ARG)>::value ]]), - do_not_bind_functions_with_nonconst_ref); +template <typename Runnable, typename RunType[[]] +$if ARITY > 0[[, ]] $for ARG , [[typename P$(ARG)]]> +struct BindState<Runnable, RunType, void($for ARG , [[P$(ARG)]])> : public BindStateBase { + typedef Runnable RunnableType; +$if ARITY > 0 [[ + typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall; +]] $else [[ + typedef false_type IsWeakCall; ]] + typedef Invoker<$(ARITY), BindState, RunType> InvokerType; + typedef typename InvokerType::UnboundRunType UnboundRunType; + +$if ARITY > 0 [[ + + // Convenience typedefs for bound argument types. + +$for ARG [[ + typedef UnwrapTraits<P$(ARG)> Bound$(ARG)UnwrapTraits; + +]] $$ for ARG + + +]] $$ if ARITY > 0 - InvokerStorage$(BOUND)(Sig f -$if BOUND > 0 [[, ]] -$for BOUND_ARG , [[const P$(BOUND_ARG)& p$(BOUND_ARG)]]) - : f_(f)[[]] -$if BOUND == 0 [[ +$$ The extra [[ ]] is needed to massage spacing. Silly pump.py. +[[ ]]$if ARITY == 0 [[explicit ]]BindState(const Runnable& runnable +$if ARITY > 0 [[, ]] $for ARG , [[const P$(ARG)& p$(ARG)]]) + : runnable_(runnable)[[]] +$if ARITY == 0 [[ { ]] $else [[ -, $for BOUND_ARG , [[p$(BOUND_ARG)_(static_cast<typename ParamTraits<P$(BOUND_ARG)>::StorageType>(p$(BOUND_ARG)))]] { - MaybeRefcount<IsMethod, P1>::AddRef(p1_); +, $for ARG , [[ + + p$(ARG)_(p$(ARG)) +]] { + MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_); ]] } - virtual ~InvokerStorage$(BOUND)() { -$if BOUND > 0 [[ - - MaybeRefcount<IsMethod, P1>::Release(p1_); - + virtual ~BindState() { +$if ARITY > 0 [[ + MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::Release(p1_); ]] } - Sig f_; + RunnableType runnable_; -$for BOUND_ARG [[ - typename ParamTraits<P$(BOUND_ARG)>::StorageType p$(BOUND_ARG)_; +$for ARG [[ + P$(ARG) p$(ARG)_; ]] }; -]] $$ for BOUND +]] $$ for ARITY } // namespace internal } // namespace base diff --git a/base/bind_internal_win.h b/base/bind_internal_win.h index 250f472..17d3aa3 100644 --- a/base/bind_internal_win.h +++ b/base/bind_internal_win.h @@ -8,7 +8,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Specializations of FunctionTraits<> for Windows specific calling +// Specializations of RunnableAdapter<> for Windows specific calling // conventions. Please see base/bind_internal.h for more info. #ifndef BASE_BIND_INTERNAL_WIN_H_ @@ -23,203 +23,293 @@ namespace base { namespace internal { -template <typename Sig> -struct FunctionTraits; +template <typename Functor> +class RunnableAdapter; // __stdcall Function: Arity 0. template <typename R> -struct FunctionTraits<R(__stdcall *)()> { - typedef R (*NormalizedSig)(); - typedef false_type IsMethod; +class RunnableAdapter<R(__stdcall *)()> { + public: + typedef R (RunType)(); - typedef R Return; + explicit RunnableAdapter(R(__stdcall *function)()) + : function_(function) { + } + + R Run() { + return function_(); + } + + private: + R (__stdcall *function_)(); }; // __fastcall Function: Arity 0. template <typename R> -struct FunctionTraits<R(__fastcall *)()> { - typedef R (*NormalizedSig)(); - typedef false_type IsMethod; +class RunnableAdapter<R(__fastcall *)()> { + public: + typedef R (RunType)(); + + explicit RunnableAdapter(R(__fastcall *function)()) + : function_(function) { + } + + R Run() { + return function_(); + } - typedef R Return; + private: + R (__fastcall *function_)(); }; // __stdcall Function: Arity 1. -template <typename R, typename X1> -struct FunctionTraits<R(__stdcall *)(X1)> { - typedef R (*NormalizedSig)(X1); - typedef false_type IsMethod; +template <typename R, typename A1> +class RunnableAdapter<R(__stdcall *)(A1)> { + public: + typedef R (RunType)(A1); - typedef R Return; + explicit RunnableAdapter(R(__stdcall *function)(A1)) + : function_(function) { + } - // Target type for each bound parameter. - typedef X1 B1; + R Run(typename CallbackParamTraits<A1>::ForwardType a1) { + return function_(a1); + } + + private: + R (__stdcall *function_)(A1); }; // __fastcall Function: Arity 1. -template <typename R, typename X1> -struct FunctionTraits<R(__fastcall *)(X1)> { - typedef R (*NormalizedSig)(X1); - typedef false_type IsMethod; +template <typename R, typename A1> +class RunnableAdapter<R(__fastcall *)(A1)> { + public: + typedef R (RunType)(A1); + + explicit RunnableAdapter(R(__fastcall *function)(A1)) + : function_(function) { + } - typedef R Return; + R Run(typename CallbackParamTraits<A1>::ForwardType a1) { + return function_(a1); + } - // Target type for each bound parameter. - typedef X1 B1; + private: + R (__fastcall *function_)(A1); }; // __stdcall Function: Arity 2. -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; +template <typename R, typename A1, typename A2> +class RunnableAdapter<R(__stdcall *)(A1, A2)> { + public: + typedef R (RunType)(A1, A2); + + explicit RunnableAdapter(R(__stdcall *function)(A1, A2)) + : function_(function) { + } + + R Run(typename CallbackParamTraits<A1>::ForwardType a1, + typename CallbackParamTraits<A2>::ForwardType a2) { + return function_(a1, a2); + } + + private: + R (__stdcall *function_)(A1, A2); }; // __fastcall Function: Arity 2. -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; +template <typename R, typename A1, typename A2> +class RunnableAdapter<R(__fastcall *)(A1, A2)> { + public: + typedef R (RunType)(A1, A2); + + explicit RunnableAdapter(R(__fastcall *function)(A1, A2)) + : function_(function) { + } + + R Run(typename CallbackParamTraits<A1>::ForwardType a1, + typename CallbackParamTraits<A2>::ForwardType a2) { + return function_(a1, a2); + } + + private: + R (__fastcall *function_)(A1, A2); }; // __stdcall Function: Arity 3. -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; - typedef X3 B3; +template <typename R, typename A1, typename A2, typename A3> +class RunnableAdapter<R(__stdcall *)(A1, A2, A3)> { + public: + typedef R (RunType)(A1, A2, A3); + + explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3)) + : function_(function) { + } + + R Run(typename CallbackParamTraits<A1>::ForwardType a1, + typename CallbackParamTraits<A2>::ForwardType a2, + typename CallbackParamTraits<A3>::ForwardType a3) { + return function_(a1, a2, a3); + } + + private: + R (__stdcall *function_)(A1, A2, A3); }; // __fastcall Function: Arity 3. -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; - typedef X3 B3; +template <typename R, typename A1, typename A2, typename A3> +class RunnableAdapter<R(__fastcall *)(A1, A2, A3)> { + public: + typedef R (RunType)(A1, A2, A3); + + explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3)) + : function_(function) { + } + + R Run(typename CallbackParamTraits<A1>::ForwardType a1, + typename CallbackParamTraits<A2>::ForwardType a2, + typename CallbackParamTraits<A3>::ForwardType a3) { + return function_(a1, a2, a3); + } + + private: + R (__fastcall *function_)(A1, A2, A3); }; // __stdcall Function: Arity 4. -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; - typedef X3 B3; - typedef X4 B4; +template <typename R, typename A1, typename A2, typename A3, typename A4> +class RunnableAdapter<R(__stdcall *)(A1, A2, A3, A4)> { + public: + typedef R (RunType)(A1, A2, A3, A4); + + explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3, A4)) + : function_(function) { + } + + R Run(typename CallbackParamTraits<A1>::ForwardType a1, + typename CallbackParamTraits<A2>::ForwardType a2, + typename CallbackParamTraits<A3>::ForwardType a3, + typename CallbackParamTraits<A4>::ForwardType a4) { + return function_(a1, a2, a3, a4); + } + + private: + R (__stdcall *function_)(A1, A2, A3, A4); }; // __fastcall Function: Arity 4. -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; - typedef X3 B3; - typedef X4 B4; +template <typename R, typename A1, typename A2, typename A3, typename A4> +class RunnableAdapter<R(__fastcall *)(A1, A2, A3, A4)> { + public: + typedef R (RunType)(A1, A2, A3, A4); + + explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3, A4)) + : function_(function) { + } + + R Run(typename CallbackParamTraits<A1>::ForwardType a1, + typename CallbackParamTraits<A2>::ForwardType a2, + typename CallbackParamTraits<A3>::ForwardType a3, + typename CallbackParamTraits<A4>::ForwardType a4) { + return function_(a1, a2, a3, a4); + } + + private: + R (__fastcall *function_)(A1, A2, A3, A4); }; // __stdcall Function: Arity 5. -template <typename R, typename X1, typename X2, typename X3, typename X4, - typename X5> -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; - typedef X3 B3; - typedef X4 B4; - typedef X5 B5; +template <typename R, typename A1, typename A2, typename A3, typename A4, + typename A5> +class RunnableAdapter<R(__stdcall *)(A1, A2, A3, A4, A5)> { + public: + typedef R (RunType)(A1, A2, A3, A4, A5); + + explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3, A4, A5)) + : 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) { + return function_(a1, a2, a3, a4, a5); + } + + private: + R (__stdcall *function_)(A1, A2, A3, A4, A5); }; // __fastcall Function: Arity 5. -template <typename R, typename X1, typename X2, typename X3, typename X4, - typename X5> -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; - typedef X3 B3; - typedef X4 B4; - typedef X5 B5; +template <typename R, typename A1, typename A2, typename A3, typename A4, + typename A5> +class RunnableAdapter<R(__fastcall *)(A1, A2, A3, A4, A5)> { + public: + typedef R (RunType)(A1, A2, A3, A4, A5); + + explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3, A4, A5)) + : 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) { + return function_(a1, a2, a3, a4, a5); + } + + private: + R (__fastcall *function_)(A1, A2, A3, A4, A5); }; // __stdcall Function: Arity 6. -template <typename R, typename X1, typename X2, typename X3, typename X4, - typename X5, typename X6> -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; - typedef X3 B3; - typedef X4 B4; - typedef X5 B5; - typedef X6 B6; +template <typename R, typename A1, typename A2, typename A3, typename A4, + typename A5, typename A6> +class RunnableAdapter<R(__stdcall *)(A1, A2, A3, A4, A5, A6)> { + public: + typedef R (RunType)(A1, A2, A3, A4, A5, A6); + + explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3, A4, A5, A6)) + : 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) { + return function_(a1, a2, a3, a4, a5, a6); + } + + private: + R (__stdcall *function_)(A1, A2, A3, A4, A5, A6); }; // __fastcall Function: Arity 6. -template <typename R, typename X1, typename X2, typename X3, typename X4, - typename X5, typename X6> -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; - typedef X3 B3; - typedef X4 B4; - typedef X5 B5; - typedef X6 B6; +template <typename R, typename A1, typename A2, typename A3, typename A4, + typename A5, typename A6> +class RunnableAdapter<R(__fastcall *)(A1, A2, A3, A4, A5, A6)> { + public: + typedef R (RunType)(A1, A2, A3, A4, A5, A6); + + explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3, A4, A5, A6)) + : 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) { + return function_(a1, a2, a3, a4, a5, a6); + } + + private: + R (__fastcall *function_)(A1, A2, A3, A4, A5, A6); }; } // namespace internal diff --git a/base/bind_internal_win.h.pump b/base/bind_internal_win.h.pump index 80ee37d..1d3b6b4 100644 --- a/base/bind_internal_win.h.pump +++ b/base/bind_internal_win.h.pump @@ -11,7 +11,7 @@ $var MAX_ARITY = 6 // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Specializations of FunctionTraits<> for Windows specific calling +// Specializations of RunnableAdapter<> for Windows specific calling // conventions. Please see base/bind_internal.h for more info. #ifndef BASE_BIND_INTERNAL_WIN_H_ @@ -26,8 +26,8 @@ $var MAX_ARITY = 6 namespace base { namespace internal { -template <typename Sig> -struct FunctionTraits; +template <typename Functor> +class RunnableAdapter; $range ARITY 0..MAX_ARITY $for ARITY [[ @@ -35,42 +35,40 @@ $range ARG 1..ARITY // __stdcall Function: Arity $(ARITY). template <typename R[[]] -$if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> -struct FunctionTraits<R(__stdcall *)($for ARG , [[X$(ARG)]])> { - typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]); - typedef false_type IsMethod; +$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]> +class RunnableAdapter<R(__stdcall *)($for ARG , [[A$(ARG)]])> { + public: + typedef R (RunType)($for ARG , [[A$(ARG)]]); - typedef R Return; + explicit RunnableAdapter(R(__stdcall *function)($for ARG , [[A$(ARG)]])) + : function_(function) { + } -$if ARITY > 0 [[ + R Run($for ARG , [[typename CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) { + return function_($for ARG , [[a$(ARG)]]); + } - // Target type for each bound parameter. - -$for ARG [[ - typedef X$(ARG) B$(ARG); - -]] $$ for ARG -]] $$ if ARITY > 0 + private: + R (__stdcall *function_)($for ARG , [[A$(ARG)]]); }; // __fastcall Function: Arity $(ARITY). template <typename R[[]] -$if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> -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 [[ +$if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]> +class RunnableAdapter<R(__fastcall *)($for ARG , [[A$(ARG)]])> { + public: + typedef R (RunType)($for ARG , [[A$(ARG)]]); - // Target type for each bound parameter. + explicit RunnableAdapter(R(__fastcall *function)($for ARG , [[A$(ARG)]])) + : function_(function) { + } -$for ARG [[ - typedef X$(ARG) B$(ARG); + R Run($for ARG , [[typename CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) { + return function_($for ARG , [[a$(ARG)]]); + } -]] $$ for ARG -]] $$ if ARITY > 0 + private: + R (__fastcall *function_)($for ARG , [[A$(ARG)]]); }; ]] $$for ARITY diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc index 0fdd241..654a277 100644 --- a/base/bind_unittest.cc +++ b/base/bind_unittest.cc @@ -260,35 +260,28 @@ TEST_F(BindTest, ArityTest) { EXPECT_EQ(69, c6.Run(13, 12, 11, 10, 9, 14)); } -// Bind should be able to take existing Callbacks and convert to a Closure. -TEST_F(BindTest, CallbackBindMore) { - int output = 0; - Closure c; +// Test the Currying ability of the Callback system. +TEST_F(BindTest, CurryingTest) { + Callback<int(int,int,int,int,int,int)> c6 = Bind(&Sum); + EXPECT_EQ(69, c6.Run(13, 12, 11, 10, 9, 14)); - Callback<void(int)> c1 = Bind(&OutputSum, &output, 16, 8, 4, 2); - c = Bind(c1, 10); - c.Run(); - EXPECT_EQ(40, output); + Callback<int(int,int,int,int,int)> c5 = Bind(c6, 32); + EXPECT_EQ(87, c5.Run(13, 12, 11, 10, 9)); - Callback<void(int,int)> c2 = Bind(&OutputSum, &output, 16, 8, 4); - c = Bind(c2, 10, 9); - c.Run(); - EXPECT_EQ(47, output); + Callback<int(int,int,int,int)> c4 = Bind(c5, 16); + EXPECT_EQ(94, c4.Run(13, 12, 11, 10)); - Callback<void(int,int,int)> c3 = Bind(&OutputSum, &output, 16, 8); - c = Bind(c3, 10, 9, 8); - c.Run(); - EXPECT_EQ(51, output); + Callback<int(int,int,int)> c3 = Bind(c4, 8); + EXPECT_EQ(92, c3.Run(13, 12, 11)); - Callback<void(int,int,int,int)> c4 = Bind(&OutputSum, &output, 16); - c = Bind(c4, 10, 9, 8, 7); - c.Run(); - EXPECT_EQ(50, output); + Callback<int(int,int)> c2 = Bind(c3, 4); + EXPECT_EQ(85, c2.Run(13, 12)); - Callback<void(int,int,int,int,int)> c5 = Bind(&OutputSum, &output); - c = Bind(c5, 10, 9, 8, 7, 6); - c.Run(); - EXPECT_EQ(40, output); + Callback<int(int)> c1 = Bind(c2, 2); + EXPECT_EQ(75, c1.Run(13)); + + Callback<int(void)> c0 = Bind(c1, 1); + EXPECT_EQ(63, c0.Run()); } // Function type support. @@ -363,13 +356,46 @@ TEST_F(BindTest, ReturnValues) { EXPECT_EQ(51337, const_method_const_obj_cb.Run()); } -// IgnoreReturn adapter test. -// - Function with return value, and no params can be converted to Closure. -TEST_F(BindTest, IgnoreReturn) { +// IgnoreResult adapter test. +// - Function with return value. +// - Method with return value. +// - Const Method with return. +// - Method with return value bound to WeakPtr<>. +// - Const Method with return bound to WeakPtr<>. +TEST_F(BindTest, IgnoreResult) { EXPECT_CALL(static_func_mock_, IntMethod0()).WillOnce(Return(1337)); - Callback<int(void)> normal_cb = Bind(&IntFunc0); - Closure c = IgnoreReturn(normal_cb); - c.Run(); + EXPECT_CALL(has_ref_, AddRef()).Times(2); + EXPECT_CALL(has_ref_, Release()).Times(2); + EXPECT_CALL(has_ref_, IntMethod0()).WillOnce(Return(10)); + EXPECT_CALL(has_ref_, IntConstMethod0()).WillOnce(Return(11)); + EXPECT_CALL(no_ref_, IntMethod0()).WillOnce(Return(12)); + EXPECT_CALL(no_ref_, IntConstMethod0()).WillOnce(Return(13)); + + Closure normal_func_cb = Bind(IgnoreResult(&IntFunc0)); + normal_func_cb.Run(); + + Closure non_void_method_cb = + Bind(IgnoreResult(&HasRef::IntMethod0), &has_ref_); + non_void_method_cb.Run(); + + Closure non_void_const_method_cb = + Bind(IgnoreResult(&HasRef::IntConstMethod0), &has_ref_); + non_void_const_method_cb.Run(); + + WeakPtrFactory<NoRef> weak_factory(&no_ref_); + WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_); + + Closure non_void_weak_method_cb = + Bind(IgnoreResult(&NoRef::IntMethod0), weak_factory.GetWeakPtr()); + non_void_weak_method_cb.Run(); + + Closure non_void_weak_const_method_cb = + Bind(IgnoreResult(&NoRef::IntConstMethod0), weak_factory.GetWeakPtr()); + non_void_weak_const_method_cb.Run(); + + weak_factory.InvalidateWeakPtrs(); + non_void_weak_const_method_cb.Run(); + non_void_weak_method_cb.Run(); } // Argument binding tests. @@ -453,7 +479,7 @@ TEST_F(BindTest, UnboundArgumentTypeSupport) { } // Function with unbound reference parameter. -// - Original paraemter is modified by callback. +// - Original parameter is modified by callback. TEST_F(BindTest, UnboundReferenceSupport) { int n = 0; Callback<void(int&)> unbound_ref_cb = Bind(&RefArgSet); @@ -554,15 +580,15 @@ TEST_F(BindTest, WeakPtr) { WeakPtrFactory<NoRef> weak_factory(&no_ref_); WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_); - Callback<void(void)> method_cb = + Closure method_cb = Bind(&NoRef::VoidMethod0, weak_factory.GetWeakPtr()); method_cb.Run(); - Callback<void(void)> const_method_cb = + Closure const_method_cb = Bind(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr()); const_method_cb.Run(); - Callback<void(void)> const_method_const_ptr_cb = + Closure const_method_const_ptr_cb = Bind(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr()); const_method_const_ptr_cb.Run(); diff --git a/base/bind_unittest.nc b/base/bind_unittest.nc index eba8747..069092c 100644 --- a/base/bind_unittest.nc +++ b/base/bind_unittest.nc @@ -4,6 +4,7 @@ #include "base/callback.h" #include "base/bind.h" +#include "base/memory/ref_counted.h" namespace base { @@ -21,10 +22,7 @@ class NoRef { int IntMethod0() { return 1; } }; -class HasRef : public NoRef { - public: - void AddRef(void) const {} - bool Release(void) const { return true; } +class HasRef : public NoRef, public base::RefCounted<HasRef> { }; class Parent { @@ -175,6 +173,9 @@ void WontCompile() { // Refcounted types should not be bound as a raw pointer. void WontCompile() { HasRef for_raw_ptr; + int a; + Callback<void(void)> ref_count_as_raw_ptr_a = + Bind(&VoidPolymorphic1<int*>, &a); Callback<void(void)> ref_count_as_raw_ptr = Bind(&VoidPolymorphic1<HasRef*>, &for_raw_ptr); } @@ -190,7 +191,7 @@ void WontCompile() { weak_ptr_with_non_void_return_type.Run(); } -#elif defined(NCTEST_DISALLOW_ASSIGN_DIFFERINT_TYPES) // [r"creating array with negative size"] +#elif defined(NCTEST_DISALLOW_ASSIGN_DIFFERINT_TYPES) // [r"invalid conversion from"] // Bind result cannot be assigned to Callbacks with a mismatching type. void WontCompile() { diff --git a/base/callback.h b/base/callback.h index 7579cef..6844cc5 100644 --- a/base/callback.h +++ b/base/callback.h @@ -126,26 +126,26 @@ // The Callback classes represent a generic function pointer. Internally, // it stores a refcounted piece of state that represents the target function // and all its bound parameters. Each Callback specialization has a templated -// constructor that takes an InvokerStorageHolder<> object. In the context of -// the constructor, the static type of this InvokerStorageHolder<> object +// constructor that takes an BindStateHolder<> object. In the context of +// the constructor, the static type of this BindStateHolder<> object // uniquely identifies the function it is representing, all its bound // parameters, and a DoInvoke() that is capable of invoking the target. // -// Callback's constructor is takes the InvokerStorageHolder<> that has the +// Callback's constructor is takes the BindStateHolder<> that has the // full static type and erases the target function type, and the bound // parameters. It does this by storing a pointer to the specific DoInvoke() -// function, and upcasting the state of InvokerStorageHolder<> to a -// InvokerStorageBase. This is safe as long as this InvokerStorageBase pointer +// function, and upcasting the state of BindStateHolder<> to a +// BindStateBase. This is safe as long as this BindStateBase pointer // is only used with the stored DoInvoke() pointer. // -// To create InvokerStorageHolder<> objects, we use the Bind() functions. +// To create BindStateHolder<> objects, we use the Bind() functions. // These functions, along with a set of internal templates, are reponsible for // // - Unwrapping the function signature into return type, and parameters // - Determining the number of parameters that are bound // - Creating the storage for the bound parameters // - Performing compile-time asserts to avoid error-prone behavior -// - Returning an InvokerStorageHolder<> with an DoInvoke() that has an arity +// - Returning an BindStateHolder<> with an DoInvoke() that has an arity // matching the number of unbound parameters, and knows the correct // refcounting semantics for the target object if we are binding a class // method. @@ -236,12 +236,11 @@ class Callback; template <typename R> class Callback<R(void)> : public internal::CallbackBase { public: - typedef R(*PolymorphicInvoke)( - internal::InvokerStorageBase*); + typedef R(RunType)(); Callback() : CallbackBase(NULL, NULL) { } - // We pass InvokerStorageHolder by const ref to avoid incurring an + // 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. @@ -249,13 +248,13 @@ class Callback<R(void)> : public internal::CallbackBase { // 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::InvokerStorageHolder<T>& invoker_holder) - : CallbackBase( - reinterpret_cast<InvokeFuncStorage>(&T::Invoker::DoInvoke), - &invoker_holder.invoker_storage_) { - COMPILE_ASSERT((is_same<PolymorphicInvoke, - typename T::Invoker::DoInvokeType>::value), - callback_type_does_not_match_bind_result); + 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 { @@ -266,20 +265,23 @@ class Callback<R(void)> : public internal::CallbackBase { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); - return f(invoker_storage_.get()); + return f(bind_state_.get()); } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*); + }; template <typename R, typename A1> class Callback<R(A1)> : public internal::CallbackBase { public: - typedef R(*PolymorphicInvoke)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<A1>::ForwardType); + typedef R(RunType)(A1); Callback() : CallbackBase(NULL, NULL) { } - // We pass InvokerStorageHolder by const ref to avoid incurring an + // 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. @@ -287,38 +289,41 @@ class Callback<R(A1)> : public internal::CallbackBase { // 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::InvokerStorageHolder<T>& invoker_holder) - : CallbackBase( - reinterpret_cast<InvokeFuncStorage>(&T::Invoker::DoInvoke), - &invoker_holder.invoker_storage_) { - COMPILE_ASSERT((is_same<PolymorphicInvoke, - typename T::Invoker::DoInvokeType>::value), - callback_type_does_not_match_bind_result); + 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::ParamTraits<A1>::ForwardType a1) const { + R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); - return f(invoker_storage_.get(), a1); + return f(bind_state_.get(), a1); } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*, + typename internal::CallbackParamTraits<A1>::ForwardType); + }; template <typename R, typename A1, typename A2> class Callback<R(A1, A2)> : public internal::CallbackBase { public: - typedef R(*PolymorphicInvoke)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<A1>::ForwardType, - typename internal::ParamTraits<A2>::ForwardType); + typedef R(RunType)(A1, A2); Callback() : CallbackBase(NULL, NULL) { } - // We pass InvokerStorageHolder by const ref to avoid incurring an + // 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. @@ -326,41 +331,44 @@ class Callback<R(A1, A2)> : public internal::CallbackBase { // 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::InvokerStorageHolder<T>& invoker_holder) - : CallbackBase( - reinterpret_cast<InvokeFuncStorage>(&T::Invoker::DoInvoke), - &invoker_holder.invoker_storage_) { - COMPILE_ASSERT((is_same<PolymorphicInvoke, - typename T::Invoker::DoInvokeType>::value), - callback_type_does_not_match_bind_result); + 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::ParamTraits<A1>::ForwardType a1, - typename internal::ParamTraits<A2>::ForwardType a2) const { + R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1, + typename internal::CallbackParamTraits<A2>::ForwardType a2) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); - return f(invoker_storage_.get(), a1, + return f(bind_state_.get(), a1, a2); } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*, + typename internal::CallbackParamTraits<A1>::ForwardType, + typename internal::CallbackParamTraits<A2>::ForwardType); + }; template <typename R, typename A1, typename A2, typename A3> class Callback<R(A1, A2, A3)> : public internal::CallbackBase { public: - typedef R(*PolymorphicInvoke)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<A1>::ForwardType, - typename internal::ParamTraits<A2>::ForwardType, - typename internal::ParamTraits<A3>::ForwardType); + typedef R(RunType)(A1, A2, A3); Callback() : CallbackBase(NULL, NULL) { } - // We pass InvokerStorageHolder by const ref to avoid incurring an + // 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. @@ -368,44 +376,47 @@ class Callback<R(A1, A2, A3)> : public internal::CallbackBase { // 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::InvokerStorageHolder<T>& invoker_holder) - : CallbackBase( - reinterpret_cast<InvokeFuncStorage>(&T::Invoker::DoInvoke), - &invoker_holder.invoker_storage_) { - COMPILE_ASSERT((is_same<PolymorphicInvoke, - typename T::Invoker::DoInvokeType>::value), - callback_type_does_not_match_bind_result); + 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::ParamTraits<A1>::ForwardType a1, - typename internal::ParamTraits<A2>::ForwardType a2, - typename internal::ParamTraits<A3>::ForwardType a3) const { + R Run(typename internal::CallbackParamTraits<A1>::ForwardType a1, + typename internal::CallbackParamTraits<A2>::ForwardType a2, + typename internal::CallbackParamTraits<A3>::ForwardType a3) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); - return f(invoker_storage_.get(), a1, + return f(bind_state_.get(), a1, a2, a3); } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*, + typename internal::CallbackParamTraits<A1>::ForwardType, + typename internal::CallbackParamTraits<A2>::ForwardType, + typename internal::CallbackParamTraits<A3>::ForwardType); + }; template <typename R, typename A1, typename A2, typename A3, typename A4> class Callback<R(A1, A2, A3, A4)> : public internal::CallbackBase { public: - typedef R(*PolymorphicInvoke)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<A1>::ForwardType, - typename internal::ParamTraits<A2>::ForwardType, - typename internal::ParamTraits<A3>::ForwardType, - typename internal::ParamTraits<A4>::ForwardType); + typedef R(RunType)(A1, A2, A3, A4); Callback() : CallbackBase(NULL, NULL) { } - // We pass InvokerStorageHolder by const ref to avoid incurring an + // 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. @@ -413,48 +424,51 @@ class Callback<R(A1, A2, A3, A4)> : public internal::CallbackBase { // 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::InvokerStorageHolder<T>& invoker_holder) - : CallbackBase( - reinterpret_cast<InvokeFuncStorage>(&T::Invoker::DoInvoke), - &invoker_holder.invoker_storage_) { - COMPILE_ASSERT((is_same<PolymorphicInvoke, - typename T::Invoker::DoInvokeType>::value), - callback_type_does_not_match_bind_result); + 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::ParamTraits<A1>::ForwardType a1, - typename internal::ParamTraits<A2>::ForwardType a2, - typename internal::ParamTraits<A3>::ForwardType a3, - typename internal::ParamTraits<A4>::ForwardType a4) const { + 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) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); - return f(invoker_storage_.get(), a1, + return f(bind_state_.get(), a1, a2, a3, a4); } + + 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); + }; template <typename R, typename A1, typename A2, typename A3, typename A4, typename A5> class Callback<R(A1, A2, A3, A4, A5)> : public internal::CallbackBase { public: - typedef R(*PolymorphicInvoke)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<A1>::ForwardType, - typename internal::ParamTraits<A2>::ForwardType, - typename internal::ParamTraits<A3>::ForwardType, - typename internal::ParamTraits<A4>::ForwardType, - typename internal::ParamTraits<A5>::ForwardType); + typedef R(RunType)(A1, A2, A3, A4, A5); Callback() : CallbackBase(NULL, NULL) { } - // We pass InvokerStorageHolder by const ref to avoid incurring an + // 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. @@ -462,51 +476,54 @@ class Callback<R(A1, A2, A3, A4, A5)> : public internal::CallbackBase { // 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::InvokerStorageHolder<T>& invoker_holder) - : CallbackBase( - reinterpret_cast<InvokeFuncStorage>(&T::Invoker::DoInvoke), - &invoker_holder.invoker_storage_) { - COMPILE_ASSERT((is_same<PolymorphicInvoke, - typename T::Invoker::DoInvokeType>::value), - callback_type_does_not_match_bind_result); + 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::ParamTraits<A1>::ForwardType a1, - typename internal::ParamTraits<A2>::ForwardType a2, - typename internal::ParamTraits<A3>::ForwardType a3, - typename internal::ParamTraits<A4>::ForwardType a4, - typename internal::ParamTraits<A5>::ForwardType a5) const { + 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) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); - return f(invoker_storage_.get(), a1, + return f(bind_state_.get(), a1, a2, a3, a4, a5); } + + 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); + }; template <typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6> class Callback<R(A1, A2, A3, A4, A5, A6)> : public internal::CallbackBase { public: - typedef R(*PolymorphicInvoke)( - internal::InvokerStorageBase*, - typename internal::ParamTraits<A1>::ForwardType, - typename internal::ParamTraits<A2>::ForwardType, - typename internal::ParamTraits<A3>::ForwardType, - typename internal::ParamTraits<A4>::ForwardType, - typename internal::ParamTraits<A5>::ForwardType, - typename internal::ParamTraits<A6>::ForwardType); + typedef R(RunType)(A1, A2, A3, A4, A5, A6); Callback() : CallbackBase(NULL, NULL) { } - // We pass InvokerStorageHolder by const ref to avoid incurring an + // 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. @@ -514,35 +531,46 @@ class Callback<R(A1, A2, A3, A4, A5, A6)> : public internal::CallbackBase { // 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::InvokerStorageHolder<T>& invoker_holder) - : CallbackBase( - reinterpret_cast<InvokeFuncStorage>(&T::Invoker::DoInvoke), - &invoker_holder.invoker_storage_) { - COMPILE_ASSERT((is_same<PolymorphicInvoke, - typename T::Invoker::DoInvokeType>::value), - callback_type_does_not_match_bind_result); + 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::ParamTraits<A1>::ForwardType a1, - typename internal::ParamTraits<A2>::ForwardType a2, - typename internal::ParamTraits<A3>::ForwardType a3, - typename internal::ParamTraits<A4>::ForwardType a4, - typename internal::ParamTraits<A5>::ForwardType a5, - typename internal::ParamTraits<A6>::ForwardType a6) const { + 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) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); - return f(invoker_storage_.get(), a1, + return f(bind_state_.get(), a1, a2, a3, a4, a5, a6); } + + 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); + }; diff --git a/base/callback.h.pump b/base/callback.h.pump index 8aecdc8..eee3371 100644 --- a/base/callback.h.pump +++ b/base/callback.h.pump @@ -129,26 +129,26 @@ $var MAX_ARITY = 6 // The Callback classes represent a generic function pointer. Internally, // it stores a refcounted piece of state that represents the target function // and all its bound parameters. Each Callback specialization has a templated -// constructor that takes an InvokerStorageHolder<> object. In the context of -// the constructor, the static type of this InvokerStorageHolder<> object +// constructor that takes an BindStateHolder<> object. In the context of +// the constructor, the static type of this BindStateHolder<> object // uniquely identifies the function it is representing, all its bound // parameters, and a DoInvoke() that is capable of invoking the target. // -// Callback's constructor is takes the InvokerStorageHolder<> that has the +// Callback's constructor is takes the BindStateHolder<> that has the // full static type and erases the target function type, and the bound // parameters. It does this by storing a pointer to the specific DoInvoke() -// function, and upcasting the state of InvokerStorageHolder<> to a -// InvokerStorageBase. This is safe as long as this InvokerStorageBase pointer +// function, and upcasting the state of BindStateHolder<> to a +// BindStateBase. This is safe as long as this BindStateBase pointer // is only used with the stored DoInvoke() pointer. // -// To create InvokerStorageHolder<> objects, we use the Bind() functions. +// To create BindStateHolder<> objects, we use the Bind() functions. // These functions, along with a set of internal templates, are reponsible for // // - Unwrapping the function signature into return type, and parameters // - Determining the number of parameters that are bound // - Creating the storage for the bound parameters // - Performing compile-time asserts to avoid error-prone behavior -// - Returning an InvokerStorageHolder<> with an DoInvoke() that has an arity +// - Returning an BindStateHolder<> with an DoInvoke() that has an arity // matching the number of unbound parameters, and knows the correct // refcounting semantics for the target object if we are binding a class // method. @@ -250,14 +250,11 @@ class Callback<R($for ARG , [[A$(ARG)]])> : public internal::CallbackBase { ]] public: - typedef R(*PolymorphicInvoke)( - internal::InvokerStorageBase*[[]] -$if ARITY != 0 [[, ]] -$for ARG , [[typename internal::ParamTraits<A$(ARG)>::ForwardType]]); + typedef R(RunType)($for ARG , [[A$(ARG)]]); Callback() : CallbackBase(NULL, NULL) { } - // We pass InvokerStorageHolder by const ref to avoid incurring an + // 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. @@ -265,13 +262,13 @@ $for ARG , [[typename internal::ParamTraits<A$(ARG)>::ForwardType]]); // 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::InvokerStorageHolder<T>& invoker_holder) - : CallbackBase( - reinterpret_cast<InvokeFuncStorage>(&T::Invoker::DoInvoke), - &invoker_holder.invoker_storage_) { - COMPILE_ASSERT((is_same<PolymorphicInvoke, - typename T::Invoker::DoInvokeType>::value), - callback_type_does_not_match_bind_result); + 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 { @@ -279,15 +276,22 @@ $for ARG , [[typename internal::ParamTraits<A$(ARG)>::ForwardType]]); } R Run($for ARG , - [[typename internal::ParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) const { + [[typename internal::CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]]) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); - return f(invoker_storage_.get()[[]] + return f(bind_state_.get()[[]] $if ARITY != 0 [[, ]] $for ARG , [[a$(ARG)]]); } + + private: + typedef R(*PolymorphicInvoke)( + internal::BindStateBase*[[]] +$if ARITY != 0 [[, ]] +$for ARG , [[typename internal::CallbackParamTraits<A$(ARG)>::ForwardType]]); + }; diff --git a/base/callback_internal.cc b/base/callback_internal.cc index d9d1e6f..582fbdc 100644 --- a/base/callback_internal.cc +++ b/base/callback_internal.cc @@ -8,24 +8,24 @@ namespace base { namespace internal { bool CallbackBase::is_null() const { - return invoker_storage_.get() == NULL; + return bind_state_.get() == NULL; } void CallbackBase::Reset() { - invoker_storage_ = NULL; + bind_state_ = NULL; polymorphic_invoke_ = NULL; } bool CallbackBase::Equals(const CallbackBase& other) const { - return invoker_storage_.get() == other.invoker_storage_.get() && + return bind_state_.get() == other.bind_state_.get() && polymorphic_invoke_ == other.polymorphic_invoke_; } CallbackBase::CallbackBase(InvokeFuncStorage polymorphic_invoke, - scoped_refptr<InvokerStorageBase>* invoker_storage) + scoped_refptr<BindStateBase>* bind_state) : polymorphic_invoke_(polymorphic_invoke) { - if (invoker_storage) { - invoker_storage_.swap(*invoker_storage); + if (bind_state) { + bind_state_.swap(*bind_state); } } diff --git a/base/callback_internal.h b/base/callback_internal.h index 4f0736f..81c87c0 100644 --- a/base/callback_internal.h +++ b/base/callback_internal.h @@ -17,39 +17,39 @@ namespace base { namespace internal { -// InvokerStorageBase is used to provide an opaque handle that the Callback +// BindStateBase is used to provide an opaque handle that the Callback // class can use to represent a function object with bound arguments. It // behaves as an existential type that is used by a corresponding // DoInvoke function to perform the function execution. This allows // us to shield the Callback class from the types of the bound argument via // "type erasure." -class InvokerStorageBase : public RefCountedThreadSafe<InvokerStorageBase> { +class BindStateBase : public RefCountedThreadSafe<BindStateBase> { protected: - friend class RefCountedThreadSafe<InvokerStorageBase>; - virtual ~InvokerStorageBase() {} + friend class RefCountedThreadSafe<BindStateBase>; + virtual ~BindStateBase() {} }; -// This structure exists purely to pass the returned |invoker_storage_| from +// This structure exists purely to pass the returned |bind_state_| from // Bind() to Callback while avoiding an extra AddRef/Release() pair. // // To do this, the constructor of Callback<> must take a const-ref. The // reference must be to a const object otherwise the compiler will emit a // warning about taking a reference to a temporary. // -// Unfortunately, this means that the internal |invoker_storage_| field must +// Unfortunately, this means that the internal |bind_state_| field must // be made mutable. template <typename T> -struct InvokerStorageHolder { - explicit InvokerStorageHolder(T* invoker_storage) - : invoker_storage_(invoker_storage) { +struct BindStateHolder { + explicit BindStateHolder(T* bind_state) + : bind_state_(bind_state) { } - mutable scoped_refptr<InvokerStorageBase> invoker_storage_; + mutable scoped_refptr<BindStateBase> bind_state_; }; template <typename T> -InvokerStorageHolder<T> MakeInvokerStorageHolder(T* o) { - return InvokerStorageHolder<T>(o); +BindStateHolder<T> MakeBindStateHolder(T* o) { + return BindStateHolder<T>(o); } // Holds the Callback methods that don't require specialization to reduce @@ -73,14 +73,14 @@ class BASE_EXPORT CallbackBase { bool Equals(const CallbackBase& other) const; CallbackBase(InvokeFuncStorage polymorphic_invoke, - scoped_refptr<InvokerStorageBase>* invoker_storage); + scoped_refptr<BindStateBase>* bind_state); // Force the destructor to be instantiated inside this translation unit so // that our subclasses will not get inlined versions. Avoids more template // bloat. ~CallbackBase(); - scoped_refptr<InvokerStorageBase> invoker_storage_; + scoped_refptr<BindStateBase> bind_state_; InvokeFuncStorage polymorphic_invoke_; }; @@ -96,7 +96,7 @@ class BASE_EXPORT CallbackBase { // array type in the initializer list which C++ does not allow. This will // break passing of C-string literals. template <typename T> -struct ParamTraits { +struct CallbackParamTraits { typedef const T& ForwardType; typedef T StorageType; }; @@ -107,7 +107,7 @@ struct ParamTraits { // // The ForwardType should only be used for unbound arguments. template <typename T> -struct ParamTraits<T&> { +struct CallbackParamTraits<T&> { typedef T& ForwardType; typedef T StorageType; }; @@ -118,14 +118,14 @@ struct ParamTraits<T&> { // T[n]" does not seem to match correctly, so we are stuck with this // restriction. template <typename T, size_t n> -struct ParamTraits<T[n]> { +struct CallbackParamTraits<T[n]> { typedef const T* ForwardType; typedef const T* StorageType; }; -// See comment for ParamTraits<T[n]>. +// See comment for CallbackParamTraits<T[n]>. template <typename T> -struct ParamTraits<T[]> { +struct CallbackParamTraits<T[]> { typedef const T* ForwardType; typedef const T* StorageType; }; diff --git a/base/callback_unittest.cc b/base/callback_unittest.cc index 713c9e48..33157ae 100644 --- a/base/callback_unittest.cc +++ b/base/callback_unittest.cc @@ -23,21 +23,21 @@ class HelperObject { }; struct FakeInvoker { - typedef void(*DoInvokeType)(internal::InvokerStorageBase*); - static void DoInvoke(internal::InvokerStorageBase*) { + typedef void(RunType)(internal::BindStateBase*); + static void Run(internal::BindStateBase*) { } }; // White-box testpoints to inject into a Callback<> object for checking // comparators and emptiness APIs. -class FakeInvokerStorage1 : public internal::InvokerStorageBase { +class FakeBindState1 : public internal::BindStateBase { public: - typedef FakeInvoker Invoker; + typedef FakeInvoker InvokerType; }; -class FakeInvokerStorage2 : public internal::InvokerStorageBase { +class FakeBindState2 : public internal::BindStateBase { public: - typedef FakeInvoker Invoker; + typedef FakeInvoker InvokerType; }; TEST(CallbackOld, OneArg) { @@ -61,8 +61,8 @@ TEST(CallbackOld, ReturnValue) { class CallbackTest : public ::testing::Test { public: CallbackTest() - : callback_a_(MakeInvokerStorageHolder(new FakeInvokerStorage1())), - callback_b_(MakeInvokerStorageHolder(new FakeInvokerStorage2())) { + : callback_a_(MakeBindStateHolder(new FakeBindState1())), + callback_b_(MakeBindStateHolder(new FakeBindState2())) { } virtual ~CallbackTest() { @@ -107,7 +107,7 @@ TEST_F(CallbackTest, Equals) { // We should compare based on instance, not type. Callback<void(void)> callback_c( - MakeInvokerStorageHolder(new FakeInvokerStorage1())); + MakeBindStateHolder(new FakeBindState1())); Callback<void(void)> callback_a2 = callback_a_; EXPECT_TRUE(callback_a_.Equals(callback_a2)); EXPECT_FALSE(callback_a_.Equals(callback_c)); diff --git a/base/file_util_proxy.cc b/base/file_util_proxy.cc index 9b51d34..0873c9c 100644 --- a/base/file_util_proxy.cc +++ b/base/file_util_proxy.cc @@ -112,7 +112,8 @@ class CreateOrOpenHelper { ~CreateOrOpenHelper() { if (file_handle_ != kInvalidPlatformFileValue) { message_loop_proxy_->PostTask( - FROM_HERE, base::Bind(close_task_, file_handle_)); + FROM_HERE, + base::Bind(base::IgnoreResult(close_task_), file_handle_)); } } diff --git a/base/task_unittest.cc b/base/task_unittest.cc index d7d31fa..f192415 100644 --- a/base/task_unittest.cc +++ b/base/task_unittest.cc @@ -115,7 +115,7 @@ void Increment(int* value) { TEST(TaskTest, TestScopedClosureRunnerExitScope) { int run_count = 0; { - base::ScopedClosureRunner runner(base::Bind(Increment, &run_count)); + base::ScopedClosureRunner runner(base::Bind(&Increment, &run_count)); EXPECT_EQ(0, run_count); } EXPECT_EQ(1, run_count); @@ -125,7 +125,7 @@ TEST(TaskTest, TestScopedClosureRunnerRelease) { int run_count = 0; base::Closure c; { - base::ScopedClosureRunner runner(base::Bind(Increment, &run_count)); + base::ScopedClosureRunner runner(base::Bind(&Increment, &run_count)); c = runner.Release(); EXPECT_EQ(0, run_count); } diff --git a/base/template_util.h b/base/template_util.h index f19fb4b..916e942 100644 --- a/base/template_util.h +++ b/base/template_util.h @@ -70,7 +70,7 @@ struct ConvertHelper { static NoType Test(...); template <typename From> - static From Create(); + static From& Create(); }; // Used to determine if a type is a struct/union/class. Inspired by Boost's diff --git a/base/template_util_unittest.cc b/base/template_util_unittest.cc index daf83b6..b330a01 100644 --- a/base/template_util_unittest.cc +++ b/base/template_util_unittest.cc @@ -51,6 +51,12 @@ TEST(TemplateUtilTest, IsConvertible) { EXPECT_TRUE( (is_convertible<int, double>::value) ); EXPECT_TRUE( (is_convertible<int*, void*>::value) ); EXPECT_FALSE( (is_convertible<void*, int*>::value) ); + + // Array types are an easy corner case. Make sure to test that + // it does indeed compile. + EXPECT_FALSE( (is_convertible<int[10], double>::value) ); + EXPECT_FALSE( (is_convertible<double, int[10]>::value) ); + EXPECT_TRUE( (is_convertible<int[10], int*>::value) ); } TEST(TemplateUtilTest, IsSame) { diff --git a/build/nocompile.gypi b/build/nocompile.gypi index ef142b9..88dffc7 100644 --- a/build/nocompile.gypi +++ b/build/nocompile.gypi @@ -57,7 +57,6 @@ # least processed when things go right. { - 'sources/': [['exclude', '\\.nc$']], 'conditions': [ [ 'OS=="linux" and clang==0', { 'rules': [ diff --git a/chrome/browser/chrome_browser_main_x11.cc b/chrome/browser/chrome_browser_main_x11.cc index 8448ed5..55968ca 100644 --- a/chrome/browser/chrome_browser_main_x11.cc +++ b/chrome/browser/chrome_browser_main_x11.cc @@ -33,7 +33,7 @@ int BrowserX11ErrorHandler(Display* d, XErrorEvent* error) { if (!g_in_x11_io_error_handler) MessageLoop::current()->PostTask( FROM_HERE, - base::Bind(ui::LogErrorEventDescription, d, *error)); + base::Bind(&ui::LogErrorEventDescription, d, *error)); return 0; } diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index 854ef8b..d51c3f6 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc @@ -554,7 +554,7 @@ bool ExtensionService::UpdateExtension( if (!BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, base::Bind( - extension_file_util::DeleteFile, extension_path, false))) + &extension_file_util::DeleteFile, extension_path, false))) NOTREACHED(); return false; diff --git a/chrome/browser/extensions/extension_updater.cc b/chrome/browser/extensions/extension_updater.cc index 433e9e0..ff1b8ce 100644 --- a/chrome/browser/extensions/extension_updater.cc +++ b/chrome/browser/extensions/extension_updater.cc @@ -108,7 +108,7 @@ void RecordCRXWriteHistogram(bool success, const FilePath& crx_path) { // can not be read. Try reading. BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, - base::Bind(CheckThatCRXIsReadable, crx_path)); + base::Bind(&CheckThatCRXIsReadable, crx_path)); } } @@ -128,7 +128,7 @@ void CheckThatCRXIsReadable(const FilePath& crx_path) { BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::Bind(RecordFileUpdateHistogram, file_write_result)); + base::Bind(&RecordFileUpdateHistogram, file_write_result)); } void RecordFileUpdateHistogram(FileWriteResult file_write_result) { diff --git a/chrome/browser/net/net_pref_observer.cc b/chrome/browser/net/net_pref_observer.cc index 0eb83344..198a993 100644 --- a/chrome/browser/net/net_pref_observer.cc +++ b/chrome/browser/net/net_pref_observer.cc @@ -71,7 +71,7 @@ void NetPrefObserver::ApplySettings(const std::string* pref_name) { if (!pref_name || *pref_name == prefs::kHttpThrottlingEnabled) { BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - base::Bind(SetEnforceThrottlingOnThrottlerManager, + base::Bind(&SetEnforceThrottlingOnThrottlerManager, *http_throttling_enabled_)); } } diff --git a/chrome/browser/net/predictor.cc b/chrome/browser/net/predictor.cc index c36d3f6..54c03fa 100644 --- a/chrome/browser/net/predictor.cc +++ b/chrome/browser/net/predictor.cc @@ -799,7 +799,7 @@ void Predictor::SaveStateForNextStartupAndTrim(PrefService* prefs) { BrowserThread::IO, FROM_HERE, base::Bind( - SaveDnsPrefetchStateForNextStartupAndTrimOnIOThread, + &SaveDnsPrefetchStateForNextStartupAndTrimOnIOThread, update_startup_list.Get(), update_referral_list.Get(), &completion, diff --git a/chrome/browser/password_manager/password_store_x.cc b/chrome/browser/password_manager/password_store_x.cc index 94b27bc..fe9640d 100644 --- a/chrome/browser/password_manager/password_store_x.cc +++ b/chrome/browser/password_manager/password_store_x.cc @@ -299,6 +299,6 @@ void PasswordStoreX::SetPasswordsUseLocalProfileId(PrefService* prefs) { // This method should work on any thread, but we expect the DB thread. DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(UISetPasswordsUseLocalProfileId, prefs)); + base::Bind(&UISetPasswordsUseLocalProfileId, prefs)); } #endif // !defined(OS_MACOSX) && !defined(OS_CHROMEOS) && defined(OS_POSIX) diff --git a/chrome/common/profiling.cc b/chrome/common/profiling.cc index 946f54f..1173992 100644 --- a/chrome/common/profiling.cc +++ b/chrome/common/profiling.cc @@ -54,7 +54,7 @@ void FlushProfilingData(base::Thread* thread) { } } thread->message_loop()->PostDelayedTask( - FROM_HERE, base::Bind(FlushProfilingData, thread), flush_seconds * 1000); + FROM_HERE, base::Bind(&FlushProfilingData, thread), flush_seconds * 1000); } class ProfilingThreadControl { @@ -69,7 +69,7 @@ class ProfilingThreadControl { thread_ = new base::Thread("Profiling_Flush"); thread_->Start(); thread_->message_loop()->PostTask( - FROM_HERE, base::Bind(FlushProfilingData, thread_)); + FROM_HERE, base::Bind(&FlushProfilingData, thread_)); } void Stop() { diff --git a/content/browser/cancelable_request.h b/content/browser/cancelable_request.h index 9a986d8..0b5c5e1 100644 --- a/content/browser/cancelable_request.h +++ b/content/browser/cancelable_request.h @@ -776,13 +776,14 @@ class CancelableRequest<base::Callback<void(A1)> > : DCHECK(!callback.is_null()) << "Callback must be initialized."; } - void ForwardResult(typename base::internal::ParamTraits<A1>::ForwardType a1) { + void ForwardResult( + typename base::internal::CallbackParamTraits<A1>::ForwardType a1) { if (canceled()) return; DoForward(base::Bind(callback_, a1), false); } void ForwardResultAsync( - typename base::internal::ParamTraits<A1>::ForwardType a1) { + typename base::internal::CallbackParamTraits<A1>::ForwardType a1) { if (canceled()) return; DoForward(base::Bind(callback_, a1), true); } @@ -806,15 +807,16 @@ class CancelableRequest<base::Callback<void(A1,A2)> > : DCHECK(!callback.is_null()) << "Callback must be initialized."; } - void ForwardResult(typename base::internal::ParamTraits<A1>::ForwardType a1, - typename base::internal::ParamTraits<A2>::ForwardType a2) { + void ForwardResult( + typename base::internal::CallbackParamTraits<A1>::ForwardType a1, + typename base::internal::CallbackParamTraits<A2>::ForwardType a2) { if (canceled()) return; DoForward(base::Bind(callback_, a1, a2), false); } void ForwardResultAsync( - typename base::internal::ParamTraits<A1>::ForwardType a1, - typename base::internal::ParamTraits<A2>::ForwardType a2) { + typename base::internal::CallbackParamTraits<A1>::ForwardType a1, + typename base::internal::CallbackParamTraits<A2>::ForwardType a2) { if (canceled()) return; DoForward(base::Bind(callback_, a1, a2), true); } @@ -838,17 +840,18 @@ class CancelableRequest<base::Callback<void(A1,A2,A3)> > : DCHECK(!callback.is_null()) << "Callback must be initialized."; } - void ForwardResult(typename base::internal::ParamTraits<A1>::ForwardType a1, - typename base::internal::ParamTraits<A2>::ForwardType a2, - typename base::internal::ParamTraits<A3>::ForwardType a3) { + void ForwardResult( + typename base::internal::CallbackParamTraits<A1>::ForwardType a1, + typename base::internal::CallbackParamTraits<A2>::ForwardType a2, + typename base::internal::CallbackParamTraits<A3>::ForwardType a3) { if (canceled()) return; DoForward(base::Bind(callback_, a1, a2, a3), false); } void ForwardResultAsync( - typename base::internal::ParamTraits<A1>::ForwardType a1, - typename base::internal::ParamTraits<A2>::ForwardType a2, - typename base::internal::ParamTraits<A3>::ForwardType a3) { + typename base::internal::CallbackParamTraits<A1>::ForwardType a1, + typename base::internal::CallbackParamTraits<A2>::ForwardType a2, + typename base::internal::CallbackParamTraits<A3>::ForwardType a3) { if (canceled()) return; DoForward(base::Bind(callback_, a1, a2, a3), true); } @@ -872,19 +875,20 @@ class CancelableRequest<base::Callback<void(A1, A2, A3, A4)> > : DCHECK(!callback.is_null()) << "Callback must be initialized."; } - void ForwardResult(typename base::internal::ParamTraits<A1>::ForwardType a1, - typename base::internal::ParamTraits<A2>::ForwardType a2, - typename base::internal::ParamTraits<A3>::ForwardType a3, - typename base::internal::ParamTraits<A4>::ForwardType a4) { + void ForwardResult( + typename base::internal::CallbackParamTraits<A1>::ForwardType a1, + typename base::internal::CallbackParamTraits<A2>::ForwardType a2, + typename base::internal::CallbackParamTraits<A3>::ForwardType a3, + typename base::internal::CallbackParamTraits<A4>::ForwardType a4) { if (canceled()) return; DoForward(base::Bind(callback_, a1, a2, a3, a4), false); } void ForwardResultAsync( - typename base::internal::ParamTraits<A1>::ForwardType a1, - typename base::internal::ParamTraits<A2>::ForwardType a2, - typename base::internal::ParamTraits<A3>::ForwardType a3, - typename base::internal::ParamTraits<A4>::ForwardType a4) { + typename base::internal::CallbackParamTraits<A1>::ForwardType a1, + typename base::internal::CallbackParamTraits<A2>::ForwardType a2, + typename base::internal::CallbackParamTraits<A3>::ForwardType a3, + typename base::internal::CallbackParamTraits<A4>::ForwardType a4) { if (canceled()) return; DoForward(base::Bind(callback_, a1, a2, a3, a4), true); } @@ -908,21 +912,22 @@ class CancelableRequest<base::Callback<void(A1, A2, A3, A4, A5)> > : DCHECK(!callback.is_null()) << "Callback must be initialized."; } - void ForwardResult(typename base::internal::ParamTraits<A1>::ForwardType a1, - typename base::internal::ParamTraits<A2>::ForwardType a2, - typename base::internal::ParamTraits<A3>::ForwardType a3, - typename base::internal::ParamTraits<A4>::ForwardType a4, - typename base::internal::ParamTraits<A5>::ForwardType a5) { + void ForwardResult( + typename base::internal::CallbackParamTraits<A1>::ForwardType a1, + typename base::internal::CallbackParamTraits<A2>::ForwardType a2, + typename base::internal::CallbackParamTraits<A3>::ForwardType a3, + typename base::internal::CallbackParamTraits<A4>::ForwardType a4, + typename base::internal::CallbackParamTraits<A5>::ForwardType a5) { if (canceled()) return; DoForward(base::Bind(callback_, a1, a2, a3, a4, a5), false); } void ForwardResultAsync( - typename base::internal::ParamTraits<A1>::ForwardType a1, - typename base::internal::ParamTraits<A2>::ForwardType a2, - typename base::internal::ParamTraits<A3>::ForwardType a3, - typename base::internal::ParamTraits<A4>::ForwardType a4, - typename base::internal::ParamTraits<A5>::ForwardType a5) { + typename base::internal::CallbackParamTraits<A1>::ForwardType a1, + typename base::internal::CallbackParamTraits<A2>::ForwardType a2, + typename base::internal::CallbackParamTraits<A3>::ForwardType a3, + typename base::internal::CallbackParamTraits<A4>::ForwardType a4, + typename base::internal::CallbackParamTraits<A5>::ForwardType a5) { if (canceled()) return; DoForward(base::Bind(callback_, a1, a2, a3, a4, a5), true); } @@ -947,23 +952,24 @@ class CancelableRequest<base::Callback<void(A1, A2, A3, A4, A5, A6)> > : DCHECK(!callback.is_null()) << "Callback must be initialized."; } - void ForwardResult(typename base::internal::ParamTraits<A1>::ForwardType a1, - typename base::internal::ParamTraits<A2>::ForwardType a2, - typename base::internal::ParamTraits<A3>::ForwardType a3, - typename base::internal::ParamTraits<A4>::ForwardType a4, - typename base::internal::ParamTraits<A5>::ForwardType a5, - typename base::internal::ParamTraits<A6>::ForwardType a6) { + void ForwardResult( + typename base::internal::CallbackParamTraits<A1>::ForwardType a1, + typename base::internal::CallbackParamTraits<A2>::ForwardType a2, + typename base::internal::CallbackParamTraits<A3>::ForwardType a3, + typename base::internal::CallbackParamTraits<A4>::ForwardType a4, + typename base::internal::CallbackParamTraits<A5>::ForwardType a5, + typename base::internal::CallbackParamTraits<A6>::ForwardType a6) { if (canceled()) return; DoForward(base::Bind(callback_, a1, a2, a3, a4, a5, a6), false); } void ForwardResultAsync( - typename base::internal::ParamTraits<A1>::ForwardType a1, - typename base::internal::ParamTraits<A2>::ForwardType a2, - typename base::internal::ParamTraits<A3>::ForwardType a3, - typename base::internal::ParamTraits<A4>::ForwardType a4, - typename base::internal::ParamTraits<A5>::ForwardType a5, - typename base::internal::ParamTraits<A6>::ForwardType a6) { + typename base::internal::CallbackParamTraits<A1>::ForwardType a1, + typename base::internal::CallbackParamTraits<A2>::ForwardType a2, + typename base::internal::CallbackParamTraits<A3>::ForwardType a3, + typename base::internal::CallbackParamTraits<A4>::ForwardType a4, + typename base::internal::CallbackParamTraits<A5>::ForwardType a5, + typename base::internal::CallbackParamTraits<A6>::ForwardType a6) { if (canceled()) return; DoForward(base::Bind(callback_, a1, a2, a3, a4, a5, a6), true); } diff --git a/content/browser/debugger/worker_devtools_manager.cc b/content/browser/debugger/worker_devtools_manager.cc index a2f2f22..371314c 100644 --- a/content/browser/debugger/worker_devtools_manager.cc +++ b/content/browser/debugger/worker_devtools_manager.cc @@ -205,7 +205,7 @@ class WorkerDevToolsManager::DetachedClientHosts { static void RemovePendingWorkerData(WorkerId id) { BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - base::Bind(RemoveInspectedWorkerDataOnIOThread, id)); + base::Bind(&RemoveInspectedWorkerDataOnIOThread, id)); } static void RemoveInspectedWorkerDataOnIOThread(WorkerId id) { @@ -303,7 +303,7 @@ void WorkerDevToolsManager::WorkerDestroyed( inspected_workers_.erase(it); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::Bind(DetachedClientHosts::WorkerDestroyed, worker_id)); + base::Bind(&DetachedClientHosts::WorkerDestroyed, worker_id)); } void WorkerDevToolsManager::WorkerContextStarted(WorkerProcessHost* process, @@ -316,7 +316,7 @@ void WorkerDevToolsManager::WorkerContextStarted(WorkerProcessHost* process, BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind( - DetachedClientHosts::WorkerReloaded, + &DetachedClientHosts::WorkerReloaded, it->second, new_worker_id)); paused_workers_.erase(it); @@ -394,7 +394,7 @@ void WorkerDevToolsManager::ForwardToDevToolsClient( BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind( - ForwardToDevToolsClientOnUIThread, + &ForwardToDevToolsClientOnUIThread, worker_process_id, worker_route_id, message)); @@ -406,7 +406,7 @@ void WorkerDevToolsManager::SaveAgentRuntimeState(int worker_process_id, BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind( - SaveAgentRuntimeStateOnUIThread, + &SaveAgentRuntimeStateOnUIThread, worker_process_id, worker_route_id, state)); @@ -479,4 +479,3 @@ void WorkerDevToolsManager::SendResumeToWorker(const WorkerId& id) { if (WorkerProcessHost* process = FindWorkerProcess(id.first)) process->Send(new DevToolsAgentMsg_ResumeWorkerContext(id.second)); } - diff --git a/content/browser/plugin_service_browsertest.cc b/content/browser/plugin_service_browsertest.cc index c8f8e1e..8c2666d 100644 --- a/content/browser/plugin_service_browsertest.cc +++ b/content/browser/plugin_service_browsertest.cc @@ -247,7 +247,7 @@ IN_PROC_BROWSER_TEST_F( mock_client(browser()->profile()->GetResourceContext()); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - base::Bind(OpenChannel, &mock_client)); + base::Bind(&OpenChannel, &mock_client)); ui_test_utils::RunMessageLoop(); EXPECT_TRUE(mock_client.get_resource_context_called()); EXPECT_TRUE(mock_client.set_plugin_info_called()); @@ -299,7 +299,7 @@ IN_PROC_BROWSER_TEST_F( mock_client(browser()->profile()->GetResourceContext()); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - base::Bind(OpenChannel, &mock_client)); + base::Bind(&OpenChannel, &mock_client)); ui_test_utils::RunMessageLoop(); EXPECT_TRUE(mock_client.get_resource_context_called()); EXPECT_TRUE(mock_client.set_plugin_info_called()); diff --git a/content/renderer/render_widget_fullscreen_pepper.cc b/content/renderer/render_widget_fullscreen_pepper.cc index 9fe688d..ce90c30 100644 --- a/content/renderer/render_widget_fullscreen_pepper.cc +++ b/content/renderer/render_widget_fullscreen_pepper.cc @@ -497,7 +497,7 @@ void RenderWidgetFullscreenPepper::OnLostContext( // created when the plugin recreates its own. MessageLoop::current()->PostTask( FROM_HERE, - base::Bind(DestroyContext, context_, program_, buffer_)); + base::Bind(&DestroyContext, context_, program_, buffer_)); context_ = NULL; program_ = 0; buffer_ = 0; diff --git a/media/tools/player_x11/player_x11.cc b/media/tools/player_x11/player_x11.cc index 7676eef..0a9f2066 100644 --- a/media/tools/player_x11/player_x11.cc +++ b/media/tools/player_x11/player_x11.cc @@ -189,7 +189,7 @@ void PeriodicalUpdate( } message_loop->PostDelayedTask(FROM_HERE, base::Bind( - PeriodicalUpdate, make_scoped_refptr(pipeline), + &PeriodicalUpdate, make_scoped_refptr(pipeline), message_loop, audio_only), 10); } @@ -250,7 +250,7 @@ int main(int argc, char** argv) { audio_only = !pipeline->HasVideo(); message_loop.PostTask(FROM_HERE, base::Bind( - PeriodicalUpdate, pipeline, &message_loop, audio_only)); + &PeriodicalUpdate, pipeline, &message_loop, audio_only)); message_loop.Run(); } else{ std::cout << "Pipeline initialization failed..." << std::endl; diff --git a/remoting/protocol/jingle_session_unittest.cc b/remoting/protocol/jingle_session_unittest.cc index a4de003..35577fc 100644 --- a/remoting/protocol/jingle_session_unittest.cc +++ b/remoting/protocol/jingle_session_unittest.cc @@ -83,7 +83,7 @@ void OnTimeoutTerminateThread(bool* timeout) { bool RunMessageLoopWithTimeout(int timeout_ms) { bool timeout = false; MessageLoop::current()->PostDelayedTask( - FROM_HERE, base::Bind(OnTimeoutTerminateThread, &timeout), timeout_ms); + FROM_HERE, base::Bind(&OnTimeoutTerminateThread, &timeout), timeout_ms); MessageLoop::current()->Run(); return !timeout; } |