OLD | NEW |
(Empty) | |
| 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 $var MAX_ARITY = 6 |
| 9 |
| 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 |
| 12 // found in the LICENSE file. |
| 13 |
| 14 #ifndef BASE_PREBIND_H_ |
| 15 #define BASE_PREBIND_H_ |
| 16 #pragma once |
| 17 |
| 18 #include "base/prebind_helpers.h" |
| 19 #include "base/template_util.h" |
| 20 #include "base/uber_callback.h" |
| 21 |
| 22 namespace base { |
| 23 namespace internal { |
| 24 |
| 25 // The method by which a function is invoked is determined by 3 different |
| 26 // dimensions: |
| 27 // |
| 28 // 1) The type of function (normal, method, const-method) |
| 29 // 2) The arity of the function |
| 30 // 3) The number of bound parameters. |
| 31 // |
| 32 // The FunctionTraitsN classes unwrap the function signature type to |
| 33 // specialize based on the first two dimensions. The N in FunctionTraitsN |
| 34 // specifies the 3rd dimension. We could have specified the unbound parameters |
| 35 // via template parameters, but this method looked cleaner. |
| 36 // |
| 37 // The FunctionTraitsN contains a static DoInvoke() function that is the key to |
| 38 // implementing type erasure in the Callback() classes. DoInvoke() is a static |
| 39 // function with a fixed signature that is indepenent of StorageType; its first |
| 40 // argument is a pointer to the non-templated common baseclass of StorageType. |
| 41 // This lets us store pointer to DoInvoke() in a function pointer that has |
| 42 // knowledge of the specific StorageType, and thus no knowledge of the bound |
| 43 // function and bound parameter types. |
| 44 // |
| 45 // As long as we ensure that DoInvoke() is only used with pointers there were |
| 46 // upcasted from the correct StorageType, we can be sure that execution is |
| 47 // safe. |
| 48 |
| 49 $range PREBOUND 0..MAX_ARITY |
| 50 $for PREBOUND [[ |
| 51 |
| 52 template <typename StorageType, typename Sig> |
| 53 struct FunctionTraits$(PREBOUND); |
| 54 |
| 55 $range ARITY 0..MAX_ARITY |
| 56 $for ARITY [[ |
| 57 |
| 58 $var UNBOUND = ARITY - PREBOUND |
| 59 $if UNBOUND >= 0 [[ |
| 60 |
| 61 $$ Variables for function traits generation. |
| 62 $range ARG 1..ARITY |
| 63 $range BOUND_ARG 1..PREBOUND |
| 64 $range UNBOUND_ARG (ARITY - UNBOUND + 1)..ARITY |
| 65 |
| 66 $$ Variables for method traits generation. We are always short one arity since |
| 67 $$ the first bound parameter is the object. |
| 68 $var M_ARITY = ARITY - 1 |
| 69 $range M_ARG 1..M_ARITY |
| 70 $range M_BOUND_ARG 2..PREBOUND |
| 71 $range M_UNBOUND_ARG (M_ARITY - UNBOUND + 1)..M_ARITY |
| 72 |
| 73 // Function: Arity $(ARITY) -> $(UNBOUND). |
| 74 template <typename StorageType, typename R[[]] |
| 75 $if ARITY > 0 [[,]][[]] |
| 76 $for ARG , [[typename X$(ARG)]]> |
| 77 struct FunctionTraits$(PREBOUND)<StorageType, R(*)($for ARG , [[X$(ARG)]])> { |
| 78 $if ARITY > 0 [[ |
| 79 |
| 80 COMPILE_ASSERT( |
| 81 !($for ARG || [[ is_non_const_reference<X$(ARG)>::value ]]), |
| 82 do_not_prebind_functions_with_nonconst_ref); |
| 83 |
| 84 ]] |
| 85 |
| 86 typedef base::false_type ShouldRef; |
| 87 |
| 88 static R DoInvoke(internal::InvokerStorageBase* base[[]] |
| 89 $if UNBOUND != 0 [[, ]][[]] |
| 90 $for UNBOUND_ARG , [[const X$(UNBOUND_ARG)& x$(UNBOUND_ARG)]]) { |
| 91 StorageType* invoker = static_cast<StorageType*>(base); |
| 92 return invoker->f_($for BOUND_ARG , [[Unwrap(invoker->p$(BOUND_ARG)_)]][[]] |
| 93 $$ Add comma if there are both boudn and unbound args. |
| 94 $if UNBOUND > 0 [[$if PREBOUND > 0 [[, ]]]][[]] |
| 95 $for UNBOUND_ARG , [[x$(UNBOUND_ARG)]]); |
| 96 } |
| 97 }; |
| 98 |
| 99 $if PREBOUND > 0 [[ |
| 100 |
| 101 // Method: Arity $(M_ARITY) -> $(UNBOUND). |
| 102 template <typename StorageType, typename R, typename T[[]] |
| 103 $if M_ARITY > 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]> |
| 104 struct FunctionTraits$(PREBOUND)<StorageType, R(T::*)($for M_ARG , [[X$(M_ARG)]]
)> { |
| 105 typedef base::true_type ShouldRef; |
| 106 static R DoInvoke(internal::InvokerStorageBase* base[[]] |
| 107 $if UNBOUND > 0 [[, ]][[]] |
| 108 $for M_UNBOUND_ARG , [[const X$(M_UNBOUND_ARG)& x$(M_UNBOUND_ARG)]]) { |
| 109 StorageType* invoker = static_cast<StorageType*>(base); |
| 110 return (Unwrap(invoker->p1_)->*invoker->f_)([[]] |
| 111 $for M_BOUND_ARG , [[Unwrap(invoker->p$(M_BOUND_ARG)_)]][[]] |
| 112 $if UNBOUND > 0 [[$if PREBOUND > 1 [[, ]]]][[]] |
| 113 $for M_UNBOUND_ARG , [[x$(M_UNBOUND_ARG)]]); |
| 114 } |
| 115 }; |
| 116 |
| 117 // Const Method: Arity $(M_ARITY) -> $(UNBOUND). |
| 118 template <typename StorageType, typename R, typename T[[]] |
| 119 $if M_ARITY > 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]> |
| 120 struct FunctionTraits$(PREBOUND)<StorageType, R(T::*)($for M_ARG , [[X$(M_ARG)]]
) const> { |
| 121 typedef base::true_type ShouldRef; |
| 122 static R DoInvoke(internal::InvokerStorageBase* base[[]] |
| 123 $if UNBOUND > 0 [[, ]] |
| 124 [[]] $for M_UNBOUND_ARG , [[const X$(M_UNBOUND_ARG)& x$(M_UNBOUND_ARG)]]) { |
| 125 StorageType* invoker = static_cast<StorageType*>(base); |
| 126 return (Unwrap(invoker->p1_)->*invoker->f_)([[]] |
| 127 $for M_BOUND_ARG , [[Unwrap(invoker->p$(M_BOUND_ARG)_)]][[]] |
| 128 $if UNBOUND > 0 [[$if PREBOUND > 1 [[, ]]]][[]] |
| 129 $for M_UNBOUND_ARG , [[x$(M_UNBOUND_ARG)]]); |
| 130 } |
| 131 }; |
| 132 |
| 133 ]] $$ if PREBOUND |
| 134 |
| 135 ]] $$ if UNBOUND |
| 136 ]] $$ for ARITY |
| 137 ]] $$ for PREBOUND |
| 138 |
| 139 |
| 140 // These are the actual storage classes for the invokers. |
| 141 |
| 142 $for PREBOUND [[ |
| 143 $range BOUND_ARG 1..PREBOUND |
| 144 |
| 145 template <typename Sig[[]] |
| 146 $if PREBOUND > 0 [[, ]] |
| 147 $for BOUND_ARG , [[typename P$(BOUND_ARG)]]> |
| 148 class InvokerStorage$(PREBOUND) : public internal::InvokerStorageBase { |
| 149 public: |
| 150 typedef InvokerStorage$(PREBOUND) StorageType; |
| 151 typedef FunctionTraits$(PREBOUND)<StorageType, Sig> FunctionTraits; |
| 152 typedef typename FunctionTraits::ShouldRef ShouldRef; |
| 153 |
| 154 $if PREBOUND > 0 [[ |
| 155 |
| 156 COMPILE_ASSERT(!ShouldRef::value || !is_array<P1>::value, |
| 157 first_bound_argument_to_method_cannot_be_array); |
| 158 |
| 159 ]] |
| 160 |
| 161 InvokerStorage$(PREBOUND)(Sig f |
| 162 $if PREBOUND > 0 [[, ]] |
| 163 $for BOUND_ARG , [[const P$(BOUND_ARG)& p$(BOUND_ARG)]]) |
| 164 : f_(f)[[]] |
| 165 $if PREBOUND == 0 [[ |
| 166 { |
| 167 |
| 168 ]] $else [[ |
| 169 , $for BOUND_ARG , [[p$(BOUND_ARG)_(static_cast<typename PrebindType<P$(BOUND_AR
G)>::StorageType>(p$(BOUND_ARG)))]] { |
| 170 MaybeRefcount<ShouldRef, P1>::AddRef(p1_); |
| 171 |
| 172 ]] |
| 173 } |
| 174 |
| 175 virtual ~InvokerStorage$(PREBOUND)() { |
| 176 $if PREBOUND > 0 [[ |
| 177 |
| 178 MaybeRefcount<ShouldRef, P1>::Release(p1_); |
| 179 |
| 180 ]] |
| 181 } |
| 182 |
| 183 Sig f_; |
| 184 |
| 185 $for BOUND_ARG [[ |
| 186 typename PrebindType<P$(BOUND_ARG)>::StorageType p$(BOUND_ARG)_; |
| 187 |
| 188 ]] |
| 189 }; |
| 190 |
| 191 ]] $$ for PREBOUND |
| 192 |
| 193 } // namespace internal |
| 194 |
| 195 $for PREBOUND [[ |
| 196 $range BOUND_ARG 1..PREBOUND |
| 197 |
| 198 $if PREBOUND == 0 [[ |
| 199 |
| 200 template <typename Sig> |
| 201 internal::InvokerStorageHolder<internal::InvokerStorage0<Sig> > |
| 202 Prebind(Sig f) { |
| 203 return internal::MakeInvokerStorageHolder( |
| 204 new internal::InvokerStorage0<Sig>(f)); |
| 205 } |
| 206 |
| 207 ]] $else [[ |
| 208 |
| 209 template <typename Sig, $for BOUND_ARG , [[typename P$(BOUND_ARG)]]> |
| 210 internal::InvokerStorageHolder<internal::InvokerStorage$(PREBOUND)<Sig, |
| 211 $for BOUND_ARG , [[P$(BOUND_ARG)]]> > |
| 212 Prebind(Sig f, $for BOUND_ARG , [[const P$(BOUND_ARG)& p$(BOUND_ARG)]]) { |
| 213 return internal::MakeInvokerStorageHolder( |
| 214 new internal::InvokerStorage$(PREBOUND)<Sig, [[]] |
| 215 $for BOUND_ARG , [[P$(BOUND_ARG)]]>( |
| 216 f, $for BOUND_ARG , [[p$(BOUND_ARG)]])); |
| 217 } |
| 218 |
| 219 ]] |
| 220 |
| 221 ]] $$ for PREBOUND |
| 222 |
| 223 } // namespace base |
| 224 |
| 225 #endif // BASE_PREBIND_H_ |
OLD | NEW |