WebKit roll 98705:98715
[chromium-blink-merge.git] / base / bind_internal.h.pump
blob429e13f4e57d0016a1d5212c4f3de00116802cc9
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/raw_scoped_refptr_mismatch_checker.h"
21 #include "base/memory/weak_ptr.h"
22 #include "base/template_util.h"
23 #include "build/build_config.h"
25 #if defined(OS_WIN)
26 #include "base/bind_internal_win.h"
27 #endif
29 namespace base {
30 namespace internal {
32 // The method by which a function is invoked is determined by 3 different
33 // dimensions:
35 //   1) The type of function (normal or method).
36 //   2) The arity of the function.
37 //   3) The number of bound parameters.
39 // The templates below handle the determination of each of these dimensions.
40 // In brief:
42 //   FunctionTraits<> -- Provides a normalied signature, and other traits.
43 //   InvokerN<> -- Provides a DoInvoke() function that actually executes
44 //                 a calback.
45 //   InvokerStorageN<> -- Provides storage for the bound parameters, and
46 //                        typedefs to the above.
47 //   IsWeakMethod<> -- Determines if we are binding a method to a WeakPtr<>.
49 // More details about the design of each class is included in a comment closer
50 // to their defition.
53 // IsWeakMethod determines if we are binding a method to a WeakPtr<> for an
54 // object.  It is used to select an InvokerN that will no-op itself in the
55 // event the WeakPtr<> for the target object is invalidated.
56 template <bool IsMethod, typename T>
57 struct IsWeakMethod : public false_type {};
59 template <typename T>
60 struct IsWeakMethod<true, WeakPtr<T> > : public true_type {};
62 // FunctionTraits<>
64 // The FunctionTraits<> template determines the type of function, and also
65 // creates a NormalizedType used to select the InvokerN classes.  It turns out
66 // that syntactically, you only really have 2 variations when invoking a
67 // funciton pointer: normal, and method.  One is invoked func_ptr(arg1). The
68 // other is invoked (*obj_->method_ptr(arg1)).
70 // However, in the type system, there are many more distinctions. In standard
71 // C++, there's all variations of const, and volatile on the function pointer.
72 // In Windows, there are additional calling conventions (eg., __stdcall,
73 // __fastcall, etc.). FunctionTraits<> handles categorizing each of these into
74 // a normalized signature.
76 // Having a NormalizedSignature signature, reduces the combinatoric
77 // complexity of defintions for the InvokerN<> later.  Even though there are
78 // only 2 syntactic variations on invoking a function, without normalizing the
79 // signature, there would need to be one specialization of InvokerN for each
80 // unique (function_type, bound_arg, unbound_args) tuple in order to match all
81 // function signatures.
83 // By normalizing the function signature, we reduce function_type to exactly 2.
85 template <typename Sig>
86 struct FunctionTraits;
88 $range ARITY 0..MAX_ARITY
89 $for ARITY [[
90 $range ARG 1..ARITY
92 // Function: Arity $(ARITY).
93 template <typename R[[]]
94 $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]>
95 struct FunctionTraits<R(*)($for ARG , [[X$(ARG)]])> {
96   typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]);
97   typedef false_type IsMethod;
99   typedef R Return;
101 $if ARITY > 0 [[
103   // Target type for each bound parameter.
105 $for ARG [[
106   typedef X$(ARG) B$(ARG);
108 ]]  $$ for ARG
109 ]]  $$ if ARITY > 0
113 // Method: Arity $(ARITY).
114 template <typename R, typename T[[]]
115 $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]>
116 struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]])> {
117   typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]);
118   typedef true_type IsMethod;
120   typedef R Return;
122   // Target type for each bound parameter.
123   typedef T B1;
125 $for ARG [[
126   typedef X$(ARG) B$(ARG + 1);
128 ]]  $$ for ARG
132 // Const Method: Arity $(ARITY).
133 template <typename R, typename T[[]]
134 $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]>
135 struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]]) const> {
136   typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]);
137   typedef true_type IsMethod;
139   typedef R Return;
141   // Target type for each bound parameter.
142   typedef T B1;
144 $for ARG [[
145   typedef X$(ARG) B$(ARG + 1);
147 ]]  $$ for ARG
151 ]]  $$for ARITY
153 // InvokerN<>
155 // The InvokerN templates contain a static DoInvoke() function that is the key
156 // to implementing type erasure in the Callback() classes.
158 // DoInvoke() is a static function with a fixed signature that is independent
159 // of StorageType; its first argument is a pointer to the non-templated common
160 // baseclass of StorageType. This lets us store pointer to DoInvoke() in a
161 // function pointer that has knowledge of the specific StorageType, and thus
162 // no knowledge of the bound function and bound parameter types.
164 // As long as we ensure that DoInvoke() is only used with pointers there were
165 // upcasted from the correct StorageType, we can be sure that execution is
166 // safe.
168 // The InvokerN templates are the only point that knows the number of bound
169 // and unbound arguments.  This is intentional because it allows the other
170 // templates classes in the system to only have as many specializations as
171 // the max arity of function we wish to support.
173 $range BOUND 0..MAX_ARITY
174 $for BOUND [[
176 template <bool IsWeak, typename StorageType, typename NormalizedSig>
177 struct Invoker$(BOUND);
179 $range ARITY 0..MAX_ARITY
180 $for ARITY [[
182 $var UNBOUND = ARITY - BOUND
183 $if UNBOUND >= 0 [[
185 $$ Variables for function traits generation.
186 $range ARG 1..ARITY
187 $range BOUND_ARG 1..BOUND
188 $range UNBOUND_ARG (ARITY - UNBOUND + 1)..ARITY
190 $$ Variables for method traits generation. We are always short one arity since
191 $$ the first bound parameter is the object.
192 $var M_ARITY = ARITY - 1
193 $range M_ARG 1..M_ARITY
194 $range M_BOUND_ARG 2..BOUND
195 $range M_UNBOUND_ARG (M_ARITY - UNBOUND + 1)..M_ARITY
197 // Function: Arity $(ARITY) -> $(UNBOUND).
198 template <typename StorageType, typename R[[]]
199 $if ARITY > 0 [[,]][[]]
200 $for ARG , [[typename X$(ARG)]]>
201 struct Invoker$(BOUND)<false, StorageType, R(*)($for ARG , [[X$(ARG)]])> {
202   typedef R(*DoInvokeType)(
203       internal::InvokerStorageBase*[[]]
204 $if UNBOUND != 0 [[, ]]
205 $for UNBOUND_ARG , [[typename internal::ParamTraits<X$(UNBOUND_ARG)>::ForwardType]]);
207   static R DoInvoke(InvokerStorageBase* base[[]]
208 $if UNBOUND != 0 [[, ]][[]]
209 $for UNBOUND_ARG , [[typename internal::ParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG)]]) {
210     StorageType* invoker = static_cast<StorageType*>(base);
211     return invoker->f_($for BOUND_ARG , [[Unwrap(invoker->p$(BOUND_ARG)_)]][[]]
212 $$ Add comma if there are both boudn and unbound args.
213 $if UNBOUND > 0 [[$if BOUND > 0 [[, ]]]][[]]
214 $for UNBOUND_ARG , [[x$(UNBOUND_ARG)]]);
215   }
218 $if BOUND > 0 [[
220 // Method: Arity $(M_ARITY) -> $(UNBOUND).
221 template <typename StorageType, typename R, typename T[[]]
222 $if M_ARITY > 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]>
223 struct Invoker$(BOUND)<false, StorageType, R(T::*)($for M_ARG , [[X$(M_ARG)]])> {
224   typedef R(*DoInvokeType)(
225       internal::InvokerStorageBase*[[]]
226 $if UNBOUND != 0 [[, ]]
227 $for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::ForwardType]]);
229   static R DoInvoke(InvokerStorageBase* base[[]]
230 $if UNBOUND > 0 [[, ]][[]]
231 $for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::ForwardType x$(M_UNBOUND_ARG)]]) {
232     StorageType* invoker = static_cast<StorageType*>(base);
233     return (Unwrap(invoker->p1_)->*invoker->f_)([[]]
234 $for M_BOUND_ARG , [[Unwrap(invoker->p$(M_BOUND_ARG)_)]][[]]
235 $if UNBOUND > 0 [[$if BOUND > 1 [[, ]]]][[]]
236 $for M_UNBOUND_ARG , [[x$(M_UNBOUND_ARG)]]);
237   }
240 // WeakPtr Method: Arity $(M_ARITY) -> $(UNBOUND).
241 template <typename StorageType, typename T[[]]
242 $if M_ARITY > 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]>
243 struct Invoker$(BOUND)<true, StorageType, void(T::*)($for M_ARG , [[X$(M_ARG)]])> {
244   typedef void(*DoInvokeType)(
245       internal::InvokerStorageBase*[[]]
246 $if UNBOUND != 0 [[, ]]
247 $for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::ForwardType]]);
249   static void DoInvoke(InvokerStorageBase* base[[]]
250 $if UNBOUND > 0 [[, ]][[]]
251 $for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::ForwardType x$(M_UNBOUND_ARG)]]) {
252     StorageType* invoker = static_cast<StorageType*>(base);
253     typename StorageType::P1Traits::StorageType& weak_ptr = invoker->p1_;
254     if (!weak_ptr.get()) {
255       return;
256     }
257     (weak_ptr->*invoker->f_)([[]]
258 $for M_BOUND_ARG , [[Unwrap(invoker->p$(M_BOUND_ARG)_)]][[]]
259 $if UNBOUND > 0 [[$if BOUND > 1 [[, ]]]][[]]
260 $for M_UNBOUND_ARG , [[x$(M_UNBOUND_ARG)]]);
261   }
264 ]]  $$ if BOUND
266 ]]  $$ if UNBOUND
267 ]]  $$ for ARITY
268 ]]  $$ for BOUND
270 // BindMoreFuncN<>
272 // This set of functions help in fully binding the free parameters in a
273 // Callback<>.
274 $for BOUND [[
275 $range BOUND_ARG 1..BOUND
276 $if BOUND != 0 [[
278 template <typename Sig, $for BOUND_ARG , [[typename P$(BOUND_ARG)]]>
279 void BindMoreFunc$(BOUND)(const base::Callback<Sig>& callback, [[]]
280 $for BOUND_ARG , [[const P$(BOUND_ARG)& p$(BOUND_ARG)]]) {
281   callback.Run($for BOUND_ARG , [[p$(BOUND_ARG)]]);
284 ]]  $$ if BOUND
285 ]]  $$ for BOUND
287 // InvokerStorageN<>
289 // These are the actual storage classes for the Invokers.
291 // Though these types are "classes", they are being used as structs with
292 // all member variable public.  We cannot make it a struct because it inherits
293 // from a class which causes a compiler warning.  We cannot add a "Run()" method
294 // that forwards the unbound arguments because that would require we unwrap the
295 // Sig type like in InvokerN above to know the return type, and the arity
296 // of Run().
298 // An alternate solution would be to merge InvokerN and InvokerStorageN,
299 // but the generated code seemed harder to read.
301 $for BOUND [[
302 $range BOUND_ARG 1..BOUND
304 template <typename Sig[[]]
305 $if BOUND > 0 [[, ]]
306 $for BOUND_ARG , [[typename P$(BOUND_ARG)]]>
307 class InvokerStorage$(BOUND) : public InvokerStorageBase {
308  public:
309   typedef InvokerStorage$(BOUND) StorageType;
310   typedef FunctionTraits<Sig> TargetTraits;
311   typedef typename TargetTraits::IsMethod IsMethod;
312   typedef Sig Signature;
314 $for BOUND_ARG [[
315   typedef ParamTraits<P$(BOUND_ARG)> P$(BOUND_ARG)Traits;
319 $if BOUND == 0 [[
320   typedef Invoker$(BOUND)<false, StorageType,
321                    typename TargetTraits::NormalizedSig> Invoker;
322 ]] $else [[
323   typedef Invoker$(BOUND)<IsWeakMethod<IsMethod::value, P1>::value, StorageType,
324                    typename TargetTraits::NormalizedSig> Invoker;
325   COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) ||
326                  is_void<typename TargetTraits::Return>::value,
327                  weak_ptrs_can_only_bind_to_methods_without_return_values);
331 $for BOUND_ARG [[
332 $if BOUND_ARG == 1 [[
334   // For methods, we need to be careful for parameter 1.  We skip the
335   // scoped_refptr check because the binder itself takes care of this. We also
336   // disallow binding of an array as the method's target object.
337   COMPILE_ASSERT(IsMethod::value ||
338                  internal::NeedsScopedRefptrButGetsRawPtr<
339                      typename ParamTraits<P$(BOUND_ARG)>::StorageType>::value == 0,
340                  p$(BOUND_ARG)_is_refcounted_type_and_needs_scoped_refptr);
341   COMPILE_ASSERT(!IsMethod::value || !is_array<P$(BOUND_ARG)>::value,
342                  first_bound_argument_to_method_cannot_be_array);
343 ]] $else [[
345   COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr<
346           typename ParamTraits<P$(BOUND_ARG)>::StorageType>::value == 0,
347       p$(BOUND_ARG)_is_refcounted_type_and_needs_scoped_refptr);
348 ]]  $$ $if BOUND_ARG
349 ]]  $$ $for BOUND_ARG
352 $if BOUND > 0 [[
354   // Do not allow binding a non-const reference parameter. Non-const reference
355   // parameters are disallowed by the Google style guide.  Also, binding a
356   // non-const reference parameter can make for subtle bugs because the
357   // invoked function will receive a reference to the stored copy of the
358   // argument and not the original.
359   COMPILE_ASSERT(
360       !($for BOUND_ARG || [[ is_non_const_reference<typename TargetTraits::B$(BOUND_ARG)>::value ]]),
361       do_not_bind_functions_with_nonconst_ref);
366   InvokerStorage$(BOUND)(Sig f
367 $if BOUND > 0 [[, ]]
368 $for BOUND_ARG , [[const P$(BOUND_ARG)& p$(BOUND_ARG)]])
369       : f_(f)[[]]
370 $if BOUND == 0 [[
373 ]] $else [[
374 , $for BOUND_ARG , [[p$(BOUND_ARG)_(static_cast<typename ParamTraits<P$(BOUND_ARG)>::StorageType>(p$(BOUND_ARG)))]] {
375     MaybeRefcount<IsMethod, P1>::AddRef(p1_);
378   }
380   virtual ~InvokerStorage$(BOUND)() {
381 $if BOUND > 0 [[
383     MaybeRefcount<IsMethod, P1>::Release(p1_);
386   }
388   Sig f_;
390 $for BOUND_ARG [[
391   typename ParamTraits<P$(BOUND_ARG)>::StorageType p$(BOUND_ARG)_;
396 ]]  $$ for BOUND
398 }  // namespace internal
399 }  // namespace base
401 #endif  // BASE_BIND_INTERNAL_H_