ajwong@chromium.org | e2cca63 | 2011-02-15 10:27:38 +0900 | [diff] [blame] | 1 | $$ This is a pump file for generating file templates. Pump is a python |
| 2 | $$ script that is part of the Google Test suite of utilities. Description |
| 3 | $$ can be found here: |
| 4 | $$ |
| 5 | $$ http://code.google.com/p/googletest/wiki/PumpManual |
| 6 | $$ |
| 7 | |
ajwong@chromium.org | 6f015bd | 2011-11-29 07:13:54 +0900 | [diff] [blame] | 8 | $$ |
| 9 | $$ MAX_ARITY controls the number of arguments that Bind() supports. |
| 10 | $$ The amount of code, and more importantly, the number of template types |
| 11 | $$ generated by pump grows at O(MAX_ARITY^2). |
| 12 | $$ |
| 13 | $$ We tried going to 11 and found it imposed an extra 10 penalty on windows |
| 14 | $$ cycle times compared to our original baseline of 6. |
| 15 | $$ |
| 16 | $$ Currently 7 is chosen as a compromise between supporting a convenient |
| 17 | $$ number of arguments and keeping compile times low. At 7, we have 115 |
| 18 | $$ templates being generated by pump. |
| 19 | $$ |
| 20 | $$ Be careful when adjusting this number. If people find a need to bind |
| 21 | $$ a larger number of arguments, consider refactoring the function to use |
| 22 | $$ a param struct instead of raising the MAX_ARITY. |
| 23 | $$ |
| 24 | $$ See http://crbug.com/98542 for more context. |
| 25 | $$ |
| 26 | $var MAX_ARITY = 7 |
ajwong@chromium.org | e2cca63 | 2011-02-15 10:27:38 +0900 | [diff] [blame] | 27 | |
| 28 | // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 29 | // Use of this source code is governed by a BSD-style license that can be |
| 30 | // found in the LICENSE file. |
| 31 | |
| 32 | #ifndef BASE_BIND_H_ |
| 33 | #define BASE_BIND_H_ |
ajwong@chromium.org | e2cca63 | 2011-02-15 10:27:38 +0900 | [diff] [blame] | 34 | |
| 35 | #include "base/bind_internal.h" |
ajwong@chromium.org | fa0ff43 | 2011-02-19 08:29:31 +0900 | [diff] [blame] | 36 | #include "base/callback_internal.h" |
ajwong@chromium.org | e2cca63 | 2011-02-15 10:27:38 +0900 | [diff] [blame] | 37 | |
brettw@chromium.org | 11e3bfd | 2012-07-13 05:06:40 +0900 | [diff] [blame] | 38 | // ----------------------------------------------------------------------------- |
| 39 | // Usage documentation |
| 40 | // ----------------------------------------------------------------------------- |
ajwong@chromium.org | e2cca63 | 2011-02-15 10:27:38 +0900 | [diff] [blame] | 41 | // |
brettw@chromium.org | 11e3bfd | 2012-07-13 05:06:40 +0900 | [diff] [blame] | 42 | // See base/callback.h for documentation. |
| 43 | // |
| 44 | // |
| 45 | // ----------------------------------------------------------------------------- |
| 46 | // Implementation notes |
| 47 | // ----------------------------------------------------------------------------- |
| 48 | // |
| 49 | // If you're reading the implementation, before proceeding further, you should |
| 50 | // read the top comment of base/bind_internal.h for a definition of common |
| 51 | // terms and concepts. |
| 52 | // |
| 53 | // RETURN TYPES |
| 54 | // |
ajwong@chromium.org | e2cca63 | 2011-02-15 10:27:38 +0900 | [diff] [blame] | 55 | // Though Bind()'s result is meant to be stored in a Callback<> type, it |
| 56 | // cannot actually return the exact type without requiring a large amount |
| 57 | // of extra template specializations. The problem is that in order to |
| 58 | // discern the correct specialization of Callback<>, Bind would need to |
| 59 | // unwrap the function signature to determine the signature's arity, and |
| 60 | // whether or not it is a method. |
| 61 | // |
| 62 | // Each unique combination of (arity, function_type, num_prebound) where |
| 63 | // function_type is one of {function, method, const_method} would require |
| 64 | // one specialization. We eventually have to do a similar number of |
ajwong@chromium.org | c9c79af | 2011-11-22 04:23:44 +0900 | [diff] [blame] | 65 | // specializations anyways in the implementation (see the Invoker<>, |
ajwong@chromium.org | e2cca63 | 2011-02-15 10:27:38 +0900 | [diff] [blame] | 66 | // classes). However, it is avoidable in Bind if we return the result |
| 67 | // via an indirection like we do below. |
ajwong@chromium.org | c9c79af | 2011-11-22 04:23:44 +0900 | [diff] [blame] | 68 | // |
| 69 | // TODO(ajwong): We might be able to avoid this now, but need to test. |
| 70 | // |
| 71 | // It is possible to move most of the COMPILE_ASSERT asserts into BindState<>, |
| 72 | // but it feels a little nicer to have the asserts here so people do not |
| 73 | // need to crack open bind_internal.h. On the other hand, it makes Bind() |
| 74 | // harder to read. |
ajwong@chromium.org | e2cca63 | 2011-02-15 10:27:38 +0900 | [diff] [blame] | 75 | |
| 76 | namespace base { |
| 77 | |
ajwong@chromium.org | c9c79af | 2011-11-22 04:23:44 +0900 | [diff] [blame] | 78 | $range ARITY 0..MAX_ARITY |
| 79 | $for ARITY [[ |
| 80 | $range ARG 1..ARITY |
ajwong@chromium.org | e2cca63 | 2011-02-15 10:27:38 +0900 | [diff] [blame] | 81 | |
ajwong@chromium.org | c9c79af | 2011-11-22 04:23:44 +0900 | [diff] [blame] | 82 | template <typename Functor[[]] |
| 83 | $if ARITY > 0 [[, ]] $for ARG , [[typename P$(ARG)]]> |
ajwong@chromium.org | abd7000 | 2011-12-20 09:10:04 +0900 | [diff] [blame] | 84 | base::Callback< |
| 85 | typename internal::BindState< |
ajwong@chromium.org | c9c79af | 2011-11-22 04:23:44 +0900 | [diff] [blame] | 86 | typename internal::FunctorTraits<Functor>::RunnableType, |
| 87 | typename internal::FunctorTraits<Functor>::RunType, |
ajwong@chromium.org | abd7000 | 2011-12-20 09:10:04 +0900 | [diff] [blame] | 88 | void($for ARG , [[typename internal::CallbackParamTraits<P$(ARG)>::StorageType]])> |
| 89 | ::UnboundRunType> |
ajwong@chromium.org | c9c79af | 2011-11-22 04:23:44 +0900 | [diff] [blame] | 90 | Bind(Functor functor |
| 91 | $if ARITY > 0 [[, ]] $for ARG , [[const P$(ARG)& p$(ARG)]]) { |
| 92 | // Typedefs for how to store and run the functor. |
| 93 | typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType; |
| 94 | typedef typename internal::FunctorTraits<Functor>::RunType RunType; |
ajwong@chromium.org | e2cca63 | 2011-02-15 10:27:38 +0900 | [diff] [blame] | 95 | |
ajwong@chromium.org | c9c79af | 2011-11-22 04:23:44 +0900 | [diff] [blame] | 96 | // Use RunnableType::RunType instead of RunType above because our |
| 97 | // checks should below for bound references need to know what the actual |
| 98 | // functor is going to interpret the argument as. |
| 99 | typedef internal::FunctionTraits<typename RunnableType::RunType> |
| 100 | BoundFunctorTraits; |
ajwong@chromium.org | e2cca63 | 2011-02-15 10:27:38 +0900 | [diff] [blame] | 101 | |
ajwong@chromium.org | c9c79af | 2011-11-22 04:23:44 +0900 | [diff] [blame] | 102 | $if ARITY > 0 [[ |
| 103 | |
| 104 | // Do not allow binding a non-const reference parameter. Non-const reference |
| 105 | // parameters are disallowed by the Google style guide. Also, binding a |
| 106 | // non-const reference parameter can make for subtle bugs because the |
| 107 | // invoked function will receive a reference to the stored copy of the |
| 108 | // argument and not the original. |
| 109 | COMPILE_ASSERT( |
| 110 | !($for ARG || [[ |
| 111 | is_non_const_reference<typename BoundFunctorTraits::A$(ARG)Type>::value ]]), |
| 112 | do_not_bind_functions_with_nonconst_ref); |
| 113 | |
| 114 | ]] |
| 115 | |
| 116 | |
| 117 | $for ARG [[ |
| 118 | |
| 119 | |
| 120 | $if ARG == 1 [[ |
| 121 | // For methods, we need to be careful for parameter 1. We do not require |
| 122 | // a scoped_refptr because BindState<> itself takes care of AddRef() for |
| 123 | // methods. We also disallow binding of an array as the method's target |
| 124 | // object. |
| 125 | COMPILE_ASSERT( |
| 126 | internal::HasIsMethodTag<RunnableType>::value || |
| 127 | !internal::NeedsScopedRefptrButGetsRawPtr<P$(ARG)>::value, |
| 128 | p$(ARG)_is_refcounted_type_and_needs_scoped_refptr); |
| 129 | COMPILE_ASSERT(!internal::HasIsMethodTag<RunnableType>::value || |
| 130 | !is_array<P$(ARG)>::value, |
| 131 | first_bound_argument_to_method_cannot_be_array); |
ajwong@chromium.org | e2cca63 | 2011-02-15 10:27:38 +0900 | [diff] [blame] | 132 | ]] $else [[ |
ajwong@chromium.org | c9c79af | 2011-11-22 04:23:44 +0900 | [diff] [blame] | 133 | COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P$(ARG)>::value, |
| 134 | p$(ARG)_is_refcounted_type_and_needs_scoped_refptr); |
| 135 | ]] $$ $if ARG |
ajwong@chromium.org | e2cca63 | 2011-02-15 10:27:38 +0900 | [diff] [blame] | 136 | |
ajwong@chromium.org | c9c79af | 2011-11-22 04:23:44 +0900 | [diff] [blame] | 137 | ]] $$ $for ARG |
| 138 | |
ajwong@chromium.org | abd7000 | 2011-12-20 09:10:04 +0900 | [diff] [blame] | 139 | typedef internal::BindState<RunnableType, RunType, [[]] |
| 140 | void($for ARG , [[typename internal::CallbackParamTraits<P$(ARG)>::StorageType]])> [[]] |
| 141 | BindState; |
ajwong@chromium.org | c9c79af | 2011-11-22 04:23:44 +0900 | [diff] [blame] | 142 | |
ajwong@chromium.org | abd7000 | 2011-12-20 09:10:04 +0900 | [diff] [blame] | 143 | |
| 144 | return Callback<typename BindState::UnboundRunType>( |
| 145 | new BindState(internal::MakeRunnable(functor)[[]] |
ajwong@chromium.org | c9c79af | 2011-11-22 04:23:44 +0900 | [diff] [blame] | 146 | $if ARITY > 0 [[, ]] $for ARG , [[p$(ARG)]])); |
ajwong@chromium.org | e2cca63 | 2011-02-15 10:27:38 +0900 | [diff] [blame] | 147 | } |
| 148 | |
ajwong@chromium.org | c9c79af | 2011-11-22 04:23:44 +0900 | [diff] [blame] | 149 | ]] $$ for ARITY |
ajwong@chromium.org | e2cca63 | 2011-02-15 10:27:38 +0900 | [diff] [blame] | 150 | |
| 151 | } // namespace base |
| 152 | |
| 153 | #endif // BASE_BIND_H_ |