| OLD | NEW |
| 1 $$ This is a pump file for generating file templates. Pump is a python | 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 | 2 $$ script that is part of the Google Test suite of utilities. Description |
| 3 $$ can be found here: | 3 $$ can be found here: |
| 4 $$ | 4 $$ |
| 5 $$ http://code.google.com/p/googletest/wiki/PumpManual | 5 $$ http://code.google.com/p/googletest/wiki/PumpManual |
| 6 $$ | 6 $$ |
| 7 | 7 |
| 8 $var MAX_ARITY = 6 | 8 $var MAX_ARITY = 6 |
| 9 | 9 |
| 10 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 10 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 11 // Use of this source code is governed by a BSD-style license that can be | 11 // Use of this source code is governed by a BSD-style license that can be |
| 12 // found in the LICENSE file. | 12 // found in the LICENSE file. |
| 13 | 13 |
| 14 #ifndef BASE_BIND_INTERNAL_H_ | 14 #ifndef BASE_BIND_INTERNAL_H_ |
| 15 #define BASE_BIND_INTERNAL_H_ | 15 #define BASE_BIND_INTERNAL_H_ |
| 16 #pragma once | 16 #pragma once |
| 17 | 17 |
| 18 #include "base/bind_helpers.h" | 18 #include "base/bind_helpers.h" |
| 19 #include "base/callback_internal.h" | 19 #include "base/callback_internal.h" |
| 20 #include "base/memory/weak_ptr.h" |
| 20 #include "base/template_util.h" | 21 #include "base/template_util.h" |
| 21 #include "build/build_config.h" | 22 #include "build/build_config.h" |
| 22 | 23 |
| 23 #if defined(OS_WIN) | 24 #if defined(OS_WIN) |
| 24 #include "base/bind_internal_win.h" | 25 #include "base/bind_internal_win.h" |
| 25 #endif | 26 #endif |
| 26 | 27 |
| 27 namespace base { | 28 namespace base { |
| 28 namespace internal { | 29 namespace internal { |
| 29 | 30 |
| 30 // The method by which a function is invoked is determined by 3 different | 31 // The method by which a function is invoked is determined by 3 different |
| 31 // dimensions: | 32 // dimensions: |
| 32 // | 33 // |
| 33 // 1) The type of function (normal or method). | 34 // 1) The type of function (normal or method). |
| 34 // 2) The arity of the function. | 35 // 2) The arity of the function. |
| 35 // 3) The number of bound parameters. | 36 // 3) The number of bound parameters. |
| 36 // | 37 // |
| 37 // The templates below handle the determination of each of these dimensions. | 38 // The templates below handle the determination of each of these dimensions. |
| 38 // In brief: | 39 // In brief: |
| 39 // | 40 // |
| 40 // FunctionTraits<> -- Provides a normalied signature, and other traits. | 41 // FunctionTraits<> -- Provides a normalied signature, and other traits. |
| 41 // InvokerN<> -- Provides a DoInvoke() function that actually executes | 42 // InvokerN<> -- Provides a DoInvoke() function that actually executes |
| 42 // a calback. | 43 // a calback. |
| 43 // InvokerStorageN<> -- Provides storage for the bound parameters, and | 44 // InvokerStorageN<> -- Provides storage for the bound parameters, and |
| 44 // typedefs to the above. | 45 // typedefs to the above. |
| 46 // IsWeakMethod<> -- Determines if we are binding a method to a WeakPtr<>. |
| 45 // | 47 // |
| 46 // More details about the design of each class is included in a comment closer | 48 // More details about the design of each class is included in a comment closer |
| 47 // to their defition. | 49 // to their defition. |
| 48 | 50 |
| 51 |
| 52 // IsWeakMethod determines if we are binding a method to a WeakPtr<> for an |
| 53 // object. It is used to select an InvokerN that will no-op itself in the |
| 54 // event the WeakPtr<> for the target object is invalidated. |
| 55 template <bool IsMethod, typename T> |
| 56 struct IsWeakMethod : public false_type {}; |
| 57 |
| 58 template <typename T> |
| 59 struct IsWeakMethod<true, WeakPtr<T> > : public true_type {}; |
| 60 |
| 49 // FunctionTraits<> | 61 // FunctionTraits<> |
| 50 // | 62 // |
| 51 // The FunctionTraits<> template determines the type of function, and also | 63 // The FunctionTraits<> template determines the type of function, and also |
| 52 // creates a NormalizedType used to select the InvokerN classes. It turns out | 64 // creates a NormalizedType used to select the InvokerN classes. It turns out |
| 53 // that syntactically, you only really have 2 variations when invoking a | 65 // that syntactically, you only really have 2 variations when invoking a |
| 54 // funciton pointer: normal, and method. One is invoked func_ptr(arg1). The | 66 // funciton pointer: normal, and method. One is invoked func_ptr(arg1). The |
| 55 // other is invoked (*obj_->method_ptr(arg1)). | 67 // other is invoked (*obj_->method_ptr(arg1)). |
| 56 // | 68 // |
| 57 // However, in the type system, there are many more distinctions. In standard | 69 // However, in the type system, there are many more distinctions. In standard |
| 58 // C++, there's all variations of const, and volatile on the function pointer. | 70 // C++, there's all variations of const, and volatile on the function pointer. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 76 $for ARITY [[ | 88 $for ARITY [[ |
| 77 $range ARG 1..ARITY | 89 $range ARG 1..ARITY |
| 78 | 90 |
| 79 // Function: Arity $(ARITY). | 91 // Function: Arity $(ARITY). |
| 80 template <typename R[[]] | 92 template <typename R[[]] |
| 81 $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> | 93 $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> |
| 82 struct FunctionTraits<R(*)($for ARG , [[X$(ARG)]])> { | 94 struct FunctionTraits<R(*)($for ARG , [[X$(ARG)]])> { |
| 83 typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]); | 95 typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]); |
| 84 typedef false_type IsMethod; | 96 typedef false_type IsMethod; |
| 85 | 97 |
| 98 typedef R Return; |
| 99 |
| 86 $if ARITY > 0 [[ | 100 $if ARITY > 0 [[ |
| 87 | 101 |
| 88 // Target type for each bound parameter. | 102 // Target type for each bound parameter. |
| 89 | 103 |
| 90 $for ARG [[ | 104 $for ARG [[ |
| 91 typedef X$(ARG) B$(ARG); | 105 typedef X$(ARG) B$(ARG); |
| 92 | 106 |
| 93 ]] $$ for ARG | 107 ]] $$ for ARG |
| 94 ]] $$ if ARITY > 0 | 108 ]] $$ if ARITY > 0 |
| 95 | 109 |
| 96 }; | 110 }; |
| 97 | 111 |
| 98 // Method: Arity $(ARITY). | 112 // Method: Arity $(ARITY). |
| 99 template <typename R, typename T[[]] | 113 template <typename R, typename T[[]] |
| 100 $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> | 114 $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> |
| 101 struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]])> { | 115 struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]])> { |
| 102 typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]); | 116 typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]); |
| 103 typedef true_type IsMethod; | 117 typedef true_type IsMethod; |
| 104 | 118 |
| 119 typedef R Return; |
| 120 |
| 105 // Target type for each bound parameter. | 121 // Target type for each bound parameter. |
| 106 typedef T B1; | 122 typedef T B1; |
| 107 | 123 |
| 108 $for ARG [[ | 124 $for ARG [[ |
| 109 typedef X$(ARG) B$(ARG + 1); | 125 typedef X$(ARG) B$(ARG + 1); |
| 110 | 126 |
| 111 ]] $$ for ARG | 127 ]] $$ for ARG |
| 112 | 128 |
| 113 }; | 129 }; |
| 114 | 130 |
| 115 // Const Method: Arity $(ARITY). | 131 // Const Method: Arity $(ARITY). |
| 116 template <typename R, typename T[[]] | 132 template <typename R, typename T[[]] |
| 117 $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> | 133 $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> |
| 118 struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]]) const> { | 134 struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]]) const> { |
| 119 typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]); | 135 typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]); |
| 120 typedef true_type IsMethod; | 136 typedef true_type IsMethod; |
| 121 | 137 |
| 138 typedef R Return; |
| 139 |
| 122 // Target type for each bound parameter. | 140 // Target type for each bound parameter. |
| 123 typedef T B1; | 141 typedef T B1; |
| 124 | 142 |
| 125 $for ARG [[ | 143 $for ARG [[ |
| 126 typedef X$(ARG) B$(ARG + 1); | 144 typedef X$(ARG) B$(ARG + 1); |
| 127 | 145 |
| 128 ]] $$ for ARG | 146 ]] $$ for ARG |
| 129 | 147 |
| 130 }; | 148 }; |
| 131 | 149 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 147 // safe. | 165 // safe. |
| 148 // | 166 // |
| 149 // The InvokerN templates are the only point that knows the number of bound | 167 // The InvokerN templates are the only point that knows the number of bound |
| 150 // and unbound arguments. This is intentional because it allows the other | 168 // and unbound arguments. This is intentional because it allows the other |
| 151 // templates classes in the system to only have as many specializations as | 169 // templates classes in the system to only have as many specializations as |
| 152 // the max arity of function we wish to support. | 170 // the max arity of function we wish to support. |
| 153 | 171 |
| 154 $range BOUND 0..MAX_ARITY | 172 $range BOUND 0..MAX_ARITY |
| 155 $for BOUND [[ | 173 $for BOUND [[ |
| 156 | 174 |
| 157 template <typename StorageType, typename NormalizedSig> | 175 template <bool IsWeak, typename StorageType, typename NormalizedSig> |
| 158 struct Invoker$(BOUND); | 176 struct Invoker$(BOUND); |
| 159 | 177 |
| 160 $range ARITY 0..MAX_ARITY | 178 $range ARITY 0..MAX_ARITY |
| 161 $for ARITY [[ | 179 $for ARITY [[ |
| 162 | 180 |
| 163 $var UNBOUND = ARITY - BOUND | 181 $var UNBOUND = ARITY - BOUND |
| 164 $if UNBOUND >= 0 [[ | 182 $if UNBOUND >= 0 [[ |
| 165 | 183 |
| 166 $$ Variables for function traits generation. | 184 $$ Variables for function traits generation. |
| 167 $range ARG 1..ARITY | 185 $range ARG 1..ARITY |
| 168 $range BOUND_ARG 1..BOUND | 186 $range BOUND_ARG 1..BOUND |
| 169 $range UNBOUND_ARG (ARITY - UNBOUND + 1)..ARITY | 187 $range UNBOUND_ARG (ARITY - UNBOUND + 1)..ARITY |
| 170 | 188 |
| 171 $$ Variables for method traits generation. We are always short one arity since | 189 $$ Variables for method traits generation. We are always short one arity since |
| 172 $$ the first bound parameter is the object. | 190 $$ the first bound parameter is the object. |
| 173 $var M_ARITY = ARITY - 1 | 191 $var M_ARITY = ARITY - 1 |
| 174 $range M_ARG 1..M_ARITY | 192 $range M_ARG 1..M_ARITY |
| 175 $range M_BOUND_ARG 2..BOUND | 193 $range M_BOUND_ARG 2..BOUND |
| 176 $range M_UNBOUND_ARG (M_ARITY - UNBOUND + 1)..M_ARITY | 194 $range M_UNBOUND_ARG (M_ARITY - UNBOUND + 1)..M_ARITY |
| 177 | 195 |
| 178 // Function: Arity $(ARITY) -> $(UNBOUND). | 196 // Function: Arity $(ARITY) -> $(UNBOUND). |
| 179 template <typename StorageType, typename R[[]] | 197 template <typename StorageType, typename R[[]] |
| 180 $if ARITY > 0 [[,]][[]] | 198 $if ARITY > 0 [[,]][[]] |
| 181 $for ARG , [[typename X$(ARG)]]> | 199 $for ARG , [[typename X$(ARG)]]> |
| 182 struct Invoker$(BOUND)<StorageType, R(*)($for ARG , [[X$(ARG)]])> { | 200 struct Invoker$(BOUND)<false, StorageType, R(*)($for ARG , [[X$(ARG)]])> { |
| 183 static R DoInvoke(InvokerStorageBase* base[[]] | 201 static R DoInvoke(InvokerStorageBase* base[[]] |
| 184 $if UNBOUND != 0 [[, ]][[]] | 202 $if UNBOUND != 0 [[, ]][[]] |
| 185 $for UNBOUND_ARG , [[typename internal::ParamTraits<X$(UNBOUND_ARG)>::ForwardTyp
e x$(UNBOUND_ARG)]]) { | 203 $for UNBOUND_ARG , [[typename internal::ParamTraits<X$(UNBOUND_ARG)>::ForwardTyp
e x$(UNBOUND_ARG)]]) { |
| 186 StorageType* invoker = static_cast<StorageType*>(base); | 204 StorageType* invoker = static_cast<StorageType*>(base); |
| 187 return invoker->f_($for BOUND_ARG , [[Unwrap(invoker->p$(BOUND_ARG)_)]][[]] | 205 return invoker->f_($for BOUND_ARG , [[Unwrap(invoker->p$(BOUND_ARG)_)]][[]] |
| 188 $$ Add comma if there are both boudn and unbound args. | 206 $$ Add comma if there are both boudn and unbound args. |
| 189 $if UNBOUND > 0 [[$if BOUND > 0 [[, ]]]][[]] | 207 $if UNBOUND > 0 [[$if BOUND > 0 [[, ]]]][[]] |
| 190 $for UNBOUND_ARG , [[x$(UNBOUND_ARG)]]); | 208 $for UNBOUND_ARG , [[x$(UNBOUND_ARG)]]); |
| 191 } | 209 } |
| 192 }; | 210 }; |
| 193 | 211 |
| 194 $if BOUND > 0 [[ | 212 $if BOUND > 0 [[ |
| 195 | 213 |
| 196 // Method: Arity $(M_ARITY) -> $(UNBOUND). | 214 // Method: Arity $(M_ARITY) -> $(UNBOUND). |
| 197 template <typename StorageType, typename R, typename T[[]] | 215 template <typename StorageType, typename R, typename T[[]] |
| 198 $if M_ARITY > 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]> | 216 $if M_ARITY > 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]> |
| 199 struct Invoker$(BOUND)<StorageType, R(T::*)($for M_ARG , [[X$(M_ARG)]])> { | 217 struct Invoker$(BOUND)<false, StorageType, R(T::*)($for M_ARG , [[X$(M_ARG)]])>
{ |
| 200 static R DoInvoke(InvokerStorageBase* base[[]] | 218 static R DoInvoke(InvokerStorageBase* base[[]] |
| 201 $if UNBOUND > 0 [[, ]][[]] | 219 $if UNBOUND > 0 [[, ]][[]] |
| 202 $for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::Forwar
dType x$(M_UNBOUND_ARG)]]) { | 220 $for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::Forwar
dType x$(M_UNBOUND_ARG)]]) { |
| 203 StorageType* invoker = static_cast<StorageType*>(base); | 221 StorageType* invoker = static_cast<StorageType*>(base); |
| 204 return (Unwrap(invoker->p1_)->*invoker->f_)([[]] | 222 return (Unwrap(invoker->p1_)->*invoker->f_)([[]] |
| 205 $for M_BOUND_ARG , [[Unwrap(invoker->p$(M_BOUND_ARG)_)]][[]] | 223 $for M_BOUND_ARG , [[Unwrap(invoker->p$(M_BOUND_ARG)_)]][[]] |
| 206 $if UNBOUND > 0 [[$if BOUND > 1 [[, ]]]][[]] | 224 $if UNBOUND > 0 [[$if BOUND > 1 [[, ]]]][[]] |
| 207 $for M_UNBOUND_ARG , [[x$(M_UNBOUND_ARG)]]); | 225 $for M_UNBOUND_ARG , [[x$(M_UNBOUND_ARG)]]); |
| 208 } | 226 } |
| 209 }; | 227 }; |
| 210 | 228 |
| 229 // WeakPtr Method: Arity $(M_ARITY) -> $(UNBOUND). |
| 230 template <typename StorageType, typename T[[]] |
| 231 $if M_ARITY > 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]> |
| 232 struct Invoker$(BOUND)<true, StorageType, void(T::*)($for M_ARG , [[X$(M_ARG)]])
> { |
| 233 static void DoInvoke(InvokerStorageBase* base[[]] |
| 234 $if UNBOUND > 0 [[, ]][[]] |
| 235 $for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::Forwar
dType x$(M_UNBOUND_ARG)]]) { |
| 236 StorageType* invoker = static_cast<StorageType*>(base); |
| 237 typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_; |
| 238 if (!weak_ptr.get()) { |
| 239 return; |
| 240 } |
| 241 (weak_ptr->*invoker->f_)([[]] |
| 242 $for M_BOUND_ARG , [[Unwrap(invoker->p$(M_BOUND_ARG)_)]][[]] |
| 243 $if UNBOUND > 0 [[$if BOUND > 1 [[, ]]]][[]] |
| 244 $for M_UNBOUND_ARG , [[x$(M_UNBOUND_ARG)]]); |
| 245 } |
| 246 }; |
| 247 |
| 211 ]] $$ if BOUND | 248 ]] $$ if BOUND |
| 212 | 249 |
| 213 ]] $$ if UNBOUND | 250 ]] $$ if UNBOUND |
| 214 ]] $$ for ARITY | 251 ]] $$ for ARITY |
| 215 ]] $$ for BOUND | 252 ]] $$ for BOUND |
| 216 | 253 |
| 217 | |
| 218 // InvokerStorageN<> | 254 // InvokerStorageN<> |
| 219 // | 255 // |
| 220 // These are the actual storage classes for the Invokers. | 256 // These are the actual storage classes for the Invokers. |
| 221 // | 257 // |
| 222 // Though these types are "classes", they are being used as structs with | 258 // Though these types are "classes", they are being used as structs with |
| 223 // all member variable public. We cannot make it a struct because it inherits | 259 // all member variable public. We cannot make it a struct because it inherits |
| 224 // from a class which causes a compiler warning. We cannot add a "Run()" method | 260 // from a class which causes a compiler warning. We cannot add a "Run()" method |
| 225 // that forwards the unbound arguments because that would require we unwrap the | 261 // that forwards the unbound arguments because that would require we unwrap the |
| 226 // Sig type like in InvokerN above to know the return type, and the arity | 262 // Sig type like in InvokerN above to know the return type, and the arity |
| 227 // of Run(). | 263 // of Run(). |
| 228 // | 264 // |
| 229 // An alternate solution would be to merge InvokerN and InvokerStorageN, | 265 // An alternate solution would be to merge InvokerN and InvokerStorageN, |
| 230 // but the generated code seemed harder to read. | 266 // but the generated code seemed harder to read. |
| 231 | 267 |
| 232 $for BOUND [[ | 268 $for BOUND [[ |
| 233 $range BOUND_ARG 1..BOUND | 269 $range BOUND_ARG 1..BOUND |
| 234 | 270 |
| 235 template <typename Sig[[]] | 271 template <typename Sig[[]] |
| 236 $if BOUND > 0 [[, ]] | 272 $if BOUND > 0 [[, ]] |
| 237 $for BOUND_ARG , [[typename P$(BOUND_ARG)]]> | 273 $for BOUND_ARG , [[typename P$(BOUND_ARG)]]> |
| 238 class InvokerStorage$(BOUND) : public InvokerStorageBase { | 274 class InvokerStorage$(BOUND) : public InvokerStorageBase { |
| 239 public: | 275 public: |
| 240 typedef InvokerStorage$(BOUND) StorageType; | 276 typedef InvokerStorage$(BOUND) StorageType; |
| 241 typedef FunctionTraits<Sig> TargetTraits; | 277 typedef FunctionTraits<Sig> TargetTraits; |
| 242 typedef Invoker$(BOUND)<StorageType, typename TargetTraits::NormalizedSig> Inv
oker; | |
| 243 typedef typename TargetTraits::IsMethod IsMethod; | 278 typedef typename TargetTraits::IsMethod IsMethod; |
| 279 typedef Sig Signature; |
| 280 |
| 281 $for BOUND_ARG [[ |
| 282 typedef ParamTraits<P$(BOUND_ARG)> P$(BOUND_ARG)Traits; |
| 283 |
| 284 ]] |
| 285 |
| 286 $if BOUND == 0 [[ |
| 287 typedef Invoker$(BOUND)<false, StorageType, |
| 288 typename TargetTraits::NormalizedSig> Invoker; |
| 289 ]] $else [[ |
| 290 typedef Invoker$(BOUND)<IsWeakMethod<IsMethod::value, P1>::value, StorageType, |
| 291 typename TargetTraits::NormalizedSig> Invoker; |
| 292 COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) || |
| 293 is_void<typename TargetTraits::Return>::value, |
| 294 weak_ptrs_can_only_bind_to_methods_without_return_values); |
| 295 ]] |
| 296 |
| 244 | 297 |
| 245 $for BOUND_ARG [[ | 298 $for BOUND_ARG [[ |
| 246 $if BOUND_ARG == 1 [[ | 299 $if BOUND_ARG == 1 [[ |
| 247 | 300 |
| 248 // For methods, we need to be careful for parameter 1. We skip the | 301 // For methods, we need to be careful for parameter 1. We skip the |
| 249 // scoped_refptr check because the binder itself takes care of this. We also | 302 // scoped_refptr check because the binder itself takes care of this. We also |
| 250 // disallow binding of an array as the method's target object. | 303 // disallow binding of an array as the method's target object. |
| 251 COMPILE_ASSERT(IsMethod::value || | 304 COMPILE_ASSERT(IsMethod::value || |
| 252 !internal::UnsafeBindtoRefCountedArg<P$(BOUND_ARG)>::value, | 305 !internal::UnsafeBindtoRefCountedArg<P$(BOUND_ARG)>::value, |
| 253 p$(BOUND_ARG)_is_refcounted_type_and_needs_scoped_refptr); | 306 p$(BOUND_ARG)_is_refcounted_type_and_needs_scoped_refptr); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 304 | 357 |
| 305 ]] | 358 ]] |
| 306 }; | 359 }; |
| 307 | 360 |
| 308 ]] $$ for BOUND | 361 ]] $$ for BOUND |
| 309 | 362 |
| 310 } // namespace internal | 363 } // namespace internal |
| 311 } // namespace base | 364 } // namespace base |
| 312 | 365 |
| 313 #endif // BASE_BIND_INTERNAL_H_ | 366 #endif // BASE_BIND_INTERNAL_H_ |
| OLD | NEW |