diff options
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; } |