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 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 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_ 34 35 #include "base/bind_internal.h" 36 #include "base/callback_internal.h" 37 38 // ----------------------------------------------------------------------------- 39 // Usage documentation 40 // ----------------------------------------------------------------------------- 41 // 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 // 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 65 // specializations anyways in the implementation (see the Invoker<>, 66 // classes). However, it is avoidable in Bind if we return the result 67 // via an indirection like we do below. 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. 75 76 namespace base { 77 78 $range ARITY 0..MAX_ARITY 79 $for ARITY [[ 80 $range ARG 1..ARITY 81 82 template <typename Functor[[]] 83 $if ARITY > 0 [[, ]] $for ARG , [[typename P$(ARG)]]> 84 base::Callback< 85 typename internal::BindState< 86 typename internal::FunctorTraits<Functor>::RunnableType, 87 typename internal::FunctorTraits<Functor>::RunType, 88 void($for ARG , [[typename internal::CallbackParamTraits<P$(ARG)>::StorageType]])> 89 ::UnboundRunType> 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; 95 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; 101 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); 132 ]] $else [[ 133 COMPILE_ASSERT(!internal::NeedsScopedRefptrButGetsRawPtr<P$(ARG)>::value, 134 p$(ARG)_is_refcounted_type_and_needs_scoped_refptr); 135 ]] $$ $if ARG 136 137 ]] $$ $for ARG 138 139 typedef internal::BindState<RunnableType, RunType, [[]] 140 void($for ARG , [[typename internal::CallbackParamTraits<P$(ARG)>::StorageType]])> [[]] 141 BindState; 142 143 144 return Callback<typename BindState::UnboundRunType>( 145 new BindState(internal::MakeRunnable(functor)[[]] 146 $if ARITY > 0 [[, ]] $for ARG , [[p$(ARG)]])); 147 } 148 149 ]] $$ for ARITY 150 151 } // namespace base 152 153 #endif // BASE_BIND_H_ 154