Updating trunk VERSION from 833.0 to 834.0
[chromium-blink-merge.git] / base / bind_internal.h.pump
blob31988c54b03b2457b4c4547c9440c75da97813ab
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 $$
8 $var MAX_ARITY = 6
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.
14 #ifndef BASE_BIND_INTERNAL_H_
15 #define BASE_BIND_INTERNAL_H_
16 #pragma once
18 #include "base/bind_helpers.h"
19 #include "base/callback_internal.h"
20 #include "base/memory/weak_ptr.h"
21 #include "base/template_util.h"
22 #include "build/build_config.h"
24 #if defined(OS_WIN)
25 #include "base/bind_internal_win.h"
26 #endif
28 namespace base {
29 namespace internal {
31 // The method by which a function is invoked is determined by 3 different
32 // dimensions:
34 //   1) The type of function (normal or method).
35 //   2) The arity of the function.
36 //   3) The number of bound parameters.
38 // The templates below handle the determination of each of these dimensions.
39 // In brief:
41 //   FunctionTraits<> -- Provides a normalied signature, and other traits.
42 //   InvokerN<> -- Provides a DoInvoke() function that actually executes
43 //                 a calback.
44 //   InvokerStorageN<> -- Provides storage for the bound parameters, and
45 //                        typedefs to the above.
46 //   IsWeakMethod<> -- Determines if we are binding a method to a WeakPtr<>.
48 // More details about the design of each class is included in a comment closer
49 // to their defition.
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 {};
58 template <typename T>
59 struct IsWeakMethod<true, WeakPtr<T> > : public true_type {};
61 // FunctionTraits<>
63 // The FunctionTraits<> template determines the type of function, and also
64 // creates a NormalizedType used to select the InvokerN classes.  It turns out
65 // that syntactically, you only really have 2 variations when invoking a
66 // funciton pointer: normal, and method.  One is invoked func_ptr(arg1). The
67 // other is invoked (*obj_->method_ptr(arg1)).
69 // However, in the type system, there are many more distinctions. In standard
70 // C++, there's all variations of const, and volatile on the function pointer.
71 // In Windows, there are additional calling conventions (eg., __stdcall,
72 // __fastcall, etc.). FunctionTraits<> handles categorizing each of these into
73 // a normalized signature.
75 // Having a NormalizedSignature signature, reduces the combinatoric
76 // complexity of defintions for the InvokerN<> later.  Even though there are
77 // only 2 syntactic variations on invoking a function, without normalizing the
78 // signature, there would need to be one specialization of InvokerN for each
79 // unique (function_type, bound_arg, unbound_args) tuple in order to match all
80 // function signatures.
82 // By normalizing the function signature, we reduce function_type to exactly 2.
84 template <typename Sig>
85 struct FunctionTraits;
87 $range ARITY 0..MAX_ARITY
88 $for ARITY [[
89 $range ARG 1..ARITY
91 // Function: Arity $(ARITY).
92 template <typename R[[]]
93 $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]>
94 struct FunctionTraits<R(*)($for ARG , [[X$(ARG)]])> {
95   typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]);
96   typedef false_type IsMethod;
98   typedef R Return;
100 $if ARITY > 0 [[
102   // Target type for each bound parameter.
104 $for ARG [[
105   typedef X$(ARG) B$(ARG);
107 ]]  $$ for ARG
108 ]]  $$ if ARITY > 0
112 // Method: Arity $(ARITY).
113 template <typename R, typename T[[]]
114 $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]>
115 struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]])> {
116   typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]);
117   typedef true_type IsMethod;
119   typedef R Return;
121   // Target type for each bound parameter.
122   typedef T B1;
124 $for ARG [[
125   typedef X$(ARG) B$(ARG + 1);
127 ]]  $$ for ARG
131 // Const Method: Arity $(ARITY).
132 template <typename R, typename T[[]]
133 $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]>
134 struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]]) const> {
135   typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]);
136   typedef true_type IsMethod;
138   typedef R Return;
140   // Target type for each bound parameter.
141   typedef T B1;
143 $for ARG [[
144   typedef X$(ARG) B$(ARG + 1);
146 ]]  $$ for ARG
150 ]]  $$for ARITY
152 // InvokerN<>
154 // The InvokerN templates contain a static DoInvoke() function that is the key
155 // to implementing type erasure in the Callback() classes.
157 // DoInvoke() is a static function with a fixed signature that is independent
158 // of StorageType; its first argument is a pointer to the non-templated common
159 // baseclass of StorageType. This lets us store pointer to DoInvoke() in a
160 // function pointer that has knowledge of the specific StorageType, and thus
161 // no knowledge of the bound function and bound parameter types.
163 // As long as we ensure that DoInvoke() is only used with pointers there were
164 // upcasted from the correct StorageType, we can be sure that execution is
165 // safe.
167 // The InvokerN templates are the only point that knows the number of bound
168 // and unbound arguments.  This is intentional because it allows the other
169 // templates classes in the system to only have as many specializations as
170 // the max arity of function we wish to support.
172 $range BOUND 0..MAX_ARITY
173 $for BOUND [[
175 template <bool IsWeak, typename StorageType, typename NormalizedSig>
176 struct Invoker$(BOUND);
178 $range ARITY 0..MAX_ARITY
179 $for ARITY [[
181 $var UNBOUND = ARITY - BOUND
182 $if UNBOUND >= 0 [[
184 $$ Variables for function traits generation.
185 $range ARG 1..ARITY
186 $range BOUND_ARG 1..BOUND
187 $range UNBOUND_ARG (ARITY - UNBOUND + 1)..ARITY
189 $$ Variables for method traits generation. We are always short one arity since
190 $$ the first bound parameter is the object.
191 $var M_ARITY = ARITY - 1
192 $range M_ARG 1..M_ARITY
193 $range M_BOUND_ARG 2..BOUND
194 $range M_UNBOUND_ARG (M_ARITY - UNBOUND + 1)..M_ARITY
196 // Function: Arity $(ARITY) -> $(UNBOUND).
197 template <typename StorageType, typename R[[]]
198 $if ARITY > 0 [[,]][[]]
199 $for ARG , [[typename X$(ARG)]]>
200 struct Invoker$(BOUND)<false, StorageType, R(*)($for ARG , [[X$(ARG)]])> {
201   typedef R(*DoInvokeType)(
202       internal::InvokerStorageBase*[[]]
203 $if UNBOUND != 0 [[, ]]
204 $for UNBOUND_ARG , [[typename internal::ParamTraits<X$(UNBOUND_ARG)>::ForwardType]]);
206   static R DoInvoke(InvokerStorageBase* base[[]]
207 $if UNBOUND != 0 [[, ]][[]]
208 $for UNBOUND_ARG , [[typename internal::ParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG)]]) {
209     StorageType* invoker = static_cast<StorageType*>(base);
210     return invoker->f_($for BOUND_ARG , [[Unwrap(invoker->p$(BOUND_ARG)_)]][[]]
211 $$ Add comma if there are both boudn and unbound args.
212 $if UNBOUND > 0 [[$if BOUND > 0 [[, ]]]][[]]
213 $for UNBOUND_ARG , [[x$(UNBOUND_ARG)]]);
214   }
217 $if BOUND > 0 [[
219 // Method: Arity $(M_ARITY) -> $(UNBOUND).
220 template <typename StorageType, typename R, typename T[[]]
221 $if M_ARITY > 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]>
222 struct Invoker$(BOUND)<false, StorageType, R(T::*)($for M_ARG , [[X$(M_ARG)]])> {
223   typedef R(*DoInvokeType)(
224       internal::InvokerStorageBase*[[]]
225 $if UNBOUND != 0 [[, ]]
226 $for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::ForwardType]]);
228   static R DoInvoke(InvokerStorageBase* base[[]]
229 $if UNBOUND > 0 [[, ]][[]]
230 $for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::ForwardType x$(M_UNBOUND_ARG)]]) {
231     StorageType* invoker = static_cast<StorageType*>(base);
232     return (Unwrap(invoker->p1_)->*invoker->f_)([[]]
233 $for M_BOUND_ARG , [[Unwrap(invoker->p$(M_BOUND_ARG)_)]][[]]
234 $if UNBOUND > 0 [[$if BOUND > 1 [[, ]]]][[]]
235 $for M_UNBOUND_ARG , [[x$(M_UNBOUND_ARG)]]);
236   }
239 // WeakPtr Method: Arity $(M_ARITY) -> $(UNBOUND).
240 template <typename StorageType, typename T[[]]
241 $if M_ARITY > 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]>
242 struct Invoker$(BOUND)<true, StorageType, void(T::*)($for M_ARG , [[X$(M_ARG)]])> {
243   typedef void(*DoInvokeType)(
244       internal::InvokerStorageBase*[[]]
245 $if UNBOUND != 0 [[, ]]
246 $for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::ForwardType]]);
248   static void DoInvoke(InvokerStorageBase* base[[]]
249 $if UNBOUND > 0 [[, ]][[]]
250 $for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::ForwardType x$(M_UNBOUND_ARG)]]) {
251     StorageType* invoker = static_cast<StorageType*>(base);
252     typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
253     if (!weak_ptr.get()) {
254       return;
255     }
256     (weak_ptr->*invoker->f_)([[]]
257 $for M_BOUND_ARG , [[Unwrap(invoker->p$(M_BOUND_ARG)_)]][[]]
258 $if UNBOUND > 0 [[$if BOUND > 1 [[, ]]]][[]]
259 $for M_UNBOUND_ARG , [[x$(M_UNBOUND_ARG)]]);
260   }
263 ]]  $$ if BOUND
265 ]]  $$ if UNBOUND
266 ]]  $$ for ARITY
267 ]]  $$ for BOUND
269 // InvokerStorageN<>
271 // These are the actual storage classes for the Invokers.
273 // Though these types are "classes", they are being used as structs with
274 // all member variable public.  We cannot make it a struct because it inherits
275 // from a class which causes a compiler warning.  We cannot add a "Run()" method
276 // that forwards the unbound arguments because that would require we unwrap the
277 // Sig type like in InvokerN above to know the return type, and the arity
278 // of Run().
280 // An alternate solution would be to merge InvokerN and InvokerStorageN,
281 // but the generated code seemed harder to read.
283 $for BOUND [[
284 $range BOUND_ARG 1..BOUND
286 template <typename Sig[[]]
287 $if BOUND > 0 [[, ]]
288 $for BOUND_ARG , [[typename P$(BOUND_ARG)]]>
289 class InvokerStorage$(BOUND) : public InvokerStorageBase {
290  public:
291   typedef InvokerStorage$(BOUND) StorageType;
292   typedef FunctionTraits<Sig> TargetTraits;
293   typedef typename TargetTraits::IsMethod IsMethod;
294   typedef Sig Signature;
296 $for BOUND_ARG [[
297   typedef ParamTraits<P$(BOUND_ARG)> P$(BOUND_ARG)Traits;
301 $if BOUND == 0 [[
302   typedef Invoker$(BOUND)<false, StorageType,
303                    typename TargetTraits::NormalizedSig> Invoker;
304 ]] $else [[
305   typedef Invoker$(BOUND)<IsWeakMethod<IsMethod::value, P1>::value, StorageType,
306                    typename TargetTraits::NormalizedSig> Invoker;
307   COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) ||
308                  is_void<typename TargetTraits::Return>::value,
309                  weak_ptrs_can_only_bind_to_methods_without_return_values);
313 $for BOUND_ARG [[
314 $if BOUND_ARG == 1 [[
316   // For methods, we need to be careful for parameter 1.  We skip the
317   // scoped_refptr check because the binder itself takes care of this. We also
318   // disallow binding of an array as the method's target object.
319   COMPILE_ASSERT(IsMethod::value ||
320                  !internal::UnsafeBindtoRefCountedArg<P$(BOUND_ARG)>::value,
321                  p$(BOUND_ARG)_is_refcounted_type_and_needs_scoped_refptr);
322   COMPILE_ASSERT(!IsMethod::value || !is_array<P$(BOUND_ARG)>::value,
323                  first_bound_argument_to_method_cannot_be_array);
324 ]] $else [[
326   COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P$(BOUND_ARG)>::value,
327                  p$(BOUND_ARG)_is_refcounted_type_and_needs_scoped_refptr);
328 ]]  $$ $if BOUND_ARG
329 ]]  $$ $for BOUND_ARG
332 $if BOUND > 0 [[
334   // Do not allow binding a non-const reference parameter. Non-const reference
335   // parameters are disallowed by the Google style guide.  Also, binding a
336   // non-const reference parameter can make for subtle bugs because the
337   // invoked function will receive a reference to the stored copy of the
338   // argument and not the original.
339   COMPILE_ASSERT(
340       !($for BOUND_ARG || [[ is_non_const_reference<typename TargetTraits::B$(BOUND_ARG)>::value ]]),
341       do_not_bind_functions_with_nonconst_ref);
346   InvokerStorage$(BOUND)(Sig f
347 $if BOUND > 0 [[, ]]
348 $for BOUND_ARG , [[const P$(BOUND_ARG)& p$(BOUND_ARG)]])
349       : f_(f)[[]]
350 $if BOUND == 0 [[
353 ]] $else [[
354 , $for BOUND_ARG , [[p$(BOUND_ARG)_(static_cast<typename ParamTraits<P$(BOUND_ARG)>::StorageType>(p$(BOUND_ARG)))]] {
355     MaybeRefcount<IsMethod, P1>::AddRef(p1_);
358   }
360   virtual ~InvokerStorage$(BOUND)() {
361 $if BOUND > 0 [[
363     MaybeRefcount<IsMethod, P1>::Release(p1_);
366   }
368   Sig f_;
370 $for BOUND_ARG [[
371   typename ParamTraits<P$(BOUND_ARG)>::StorageType p$(BOUND_ARG)_;
376 ]]  $$ for BOUND
378 }  // namespace internal
379 }  // namespace base
381 #endif  // BASE_BIND_INTERNAL_H_