Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(145)

Side by Side Diff: base/bind_internal.h.pump

Issue 8483003: Callback API Change: Reimplement Bind(); support IgnoreResult, full currying, and use less types (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/bind_internal.h ('k') | base/bind_internal_win.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 // TODO(ajwong): If you create an fully unbound method, is there a way to
9 // enforce the first argument must be refcounted? Or do we just say
10 // "oh well"?
11 //
12 // Do we want to allow creating a fully unbound method??
13
8 $var MAX_ARITY = 6 14 $var MAX_ARITY = 6
15 $range ARITY 0..MAX_ARITY
9 16
10 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 17 // 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 18 // Use of this source code is governed by a BSD-style license that can be
12 // found in the LICENSE file. 19 // found in the LICENSE file.
13 20
14 #ifndef BASE_BIND_INTERNAL_H_ 21 #ifndef BASE_BIND_INTERNAL_H_
15 #define BASE_BIND_INTERNAL_H_ 22 #define BASE_BIND_INTERNAL_H_
16 #pragma once 23 #pragma once
17 24
18 #include "base/bind_helpers.h" 25 #include "base/bind_helpers.h"
19 #include "base/callback_internal.h" 26 #include "base/callback_internal.h"
20 #include "base/memory/raw_scoped_refptr_mismatch_checker.h" 27 #include "base/memory/raw_scoped_refptr_mismatch_checker.h"
21 #include "base/memory/weak_ptr.h" 28 #include "base/memory/weak_ptr.h"
22 #include "base/template_util.h" 29 #include "base/template_util.h"
23 #include "build/build_config.h" 30 #include "build/build_config.h"
24 31
25 #if defined(OS_WIN) 32 #if defined(OS_WIN)
26 #include "base/bind_internal_win.h" 33 #include "base/bind_internal_win.h"
27 #endif 34 #endif
28 35
29 namespace base { 36 namespace base {
30 namespace internal { 37 namespace internal {
31 38
32 // The method by which a function is invoked is determined by 3 different 39 // CONCEPTS:
33 // dimensions: 40 // Runnable -- A type (really a type class) that has a single Run() method
34 // 41 // and a RunType typedef that corresponds to the type of Run().
35 // 1) The type of function (normal or method). 42 // A Runnable can declare that it should treated like a method
36 // 2) The arity of the function. 43 // call by including a typedef named IsMethod. The value of
37 // 3) The number of bound parameters. 44 // this typedef is NOT inspected, only the existence. When a
38 // 45 // Runnable declares itself a method, Bind() will enforce special
39 // The templates below handle the determination of each of these dimensions. 46 // refcounting + WeakPtr handling semantics for the first
40 // In brief: 47 // parameter which is expected to be an object.
41 // 48 // Functor -- A copyable type representing something that should be called.
42 // FunctionTraits<> -- Provides a normalied signature, and other traits. 49 // All function pointers, Callback<>, and Runnables are functors
43 // InvokerN<> -- Provides a DoInvoke() function that actually executes 50 // even if the invocation syntax differs.
44 // a calback. 51 // RunType -- A function type (as opposed to function _pointer_ type) for
45 // InvokerStorageN<> -- Provides storage for the bound parameters, and 52 // a Run() function. Usually just a convenience typedef.
46 // typedefs to the above. 53 // (Bound)ArgsType -- A function type that is being (ab)used to store the
47 // IsWeakMethod<> -- Determines if we are binding a method to a WeakPtr<>. 54 // types of set of arguments. The "return" type is always
48 // 55 // void here. We use this hack so that we do not need
49 // More details about the design of each class is included in a comment closer 56 // a new type name for each arity of type. (eg.,
50 // to their defition. 57 // BindState1, BindState2). This makes forward
51 58 // declarations and friending much much easier.
52 59 //
53 // IsWeakMethod determines if we are binding a method to a WeakPtr<> for an 60 // Types:
54 // object. It is used to select an InvokerN that will no-op itself in the 61 // RunnableAdapter<> -- Wraps the various "function" pointer types into an
55 // event the WeakPtr<> for the target object is invalidated. 62 // object that adheres to the Runnable interface.
56 template <bool IsMethod, typename T> 63 // There are |3*ARITY| RunnableAdapter types.
57 struct IsWeakMethod : public false_type {}; 64 // FunctionTraits<> -- Type traits that unwrap a function signature into a
58 65 // a set of easier to use typedefs. Used mainly for
59 template <typename T> 66 // compile time asserts.
60 struct IsWeakMethod<true, WeakPtr<T> > : public true_type {}; 67 // There are |ARITY| FunctionTraits types.
68 // ForceVoidReturn<> -- Helper class for translating function signatures to
69 // equivalent forms with a "void" return type.
70 // There are |ARITY| ForceVoidReturn types.
71 // FunctorTraits<> -- Type traits used determine the correct RunType and
72 // RunnableType for a Functor. This is where function
73 // signature adapters are applied.
74 // There are |ARITY| ForceVoidReturn types.
75 // MakeRunnable<> -- Takes a Functor and returns an object in the Runnable
76 // type class that represents the underlying Functor.
77 // There are |O(1)| MakeRunnable types.
78 // InvokeHelper<> -- Take a Runnable + arguments and actully invokes it.
79 // Handle the differing syntaxes needed for WeakPtr<> support ,
80 // and for ignoring return values. This is separate from
81 // Invoker to avoid creating multiple version of Invoker<>
82 // which grows at O(n^2) with the arity.
83 // There are |k*ARITY| InvokeHelper types.
84 // Invoker<> -- Unwraps the curried parameters and executes the Runnable.
85 // There are |(ARITY^2 + ARITY)/2| Invoketypes.
86 // BindState<> -- Stores the curried parameters, and is the main entry point
87 // into the Bind() system, doing most of the type resolution.
88 // There are ARITY BindState types.
89
90
91 // RunnableAdapter<>
92 //
93 // The RunnableAdapter<> templates provide a uniform interface for invoking
94 // a function pointer, method pointer, or const method pointer. The adapter
95 // exposes a Run() method with an appropriate signature. Using this wrapper
96 // allows for writing code that supports all three pointer types without
97 // undue repetition. Without it, a lot of code would need to be repeated 3
98 // times.
99 //
100 // For method pointers and const method pointers the first argument to Run()
101 // is considered to be the received of the method. This is similar to STL's
102 // mem_fun().
103 //
104 // This class also exposes a RunType typedef that is the function type of the
105 // Run() function.
106 //
107 // If and only if the wrapper contains a method or const method pointer, an
108 // IsMethod typedef is exposed. The existence of this typedef (NOT the value)
109 // marks that the wrapper should be considered a method wrapper.
110
111 template <typename Functor>
112 class RunnableAdapter;
113
114 $for ARITY [[
115 $range ARG 1..ARITY
116
117 // Function: Arity $(ARITY).
118 template <typename R[[]]
119 $if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]>
120 class RunnableAdapter<R(*)($for ARG , [[A$(ARG)]])> {
121 public:
122 typedef R (RunType)($for ARG , [[A$(ARG)]]);
123
124 explicit RunnableAdapter(R(*function)($for ARG , [[A$(ARG)]]))
125 : function_(function) {
126 }
127
128 R Run($for ARG , [[typename CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)] ]) {
129 return function_($for ARG , [[a$(ARG)]]);
130 }
131
132 private:
133 R (*function_)($for ARG , [[A$(ARG)]]);
134 };
135
136 // Method: Arity $(ARITY).
137 template <typename R, typename T[[]]
138 $if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]>
139 class RunnableAdapter<R(T::*)($for ARG , [[A$(ARG)]])> {
140 public:
141 typedef R (RunType)(T*[[]]
142 $if ARITY > 0[[, ]] $for ARG , [[A$(ARG)]]);
143 typedef true_type IsMethod;
144
145 explicit RunnableAdapter(R(T::*method)($for ARG , [[A$(ARG)]]))
146 : method_(method) {
147 }
148
149 R Run(T* object[[]]
150 $if ARITY > 0[[, ]] $for ARG, [[typename CallbackParamTraits<A$(ARG)>::ForwardT ype a$(ARG)]]) {
151 return (object->*method_)($for ARG , [[a$(ARG)]]);
152 }
153
154 private:
155 R (T::*method_)($for ARG , [[A$(ARG)]]);
156 };
157
158 // Const Method: Arity $(ARITY).
159 template <typename R, typename T[[]]
160 $if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]>
161 class RunnableAdapter<R(T::*)($for ARG , [[A$(ARG)]]) const> {
162 public:
163 typedef R (RunType)(const T*[[]]
164 $if ARITY > 0[[, ]] $for ARG , [[A$(ARG)]]);
165 typedef true_type IsMethod;
166
167 explicit RunnableAdapter(R(T::*method)($for ARG , [[A$(ARG)]]) const)
168 : method_(method) {
169 }
170
171 R Run(const T* object[[]]
172 $if ARITY > 0[[, ]] $for ARG, [[typename CallbackParamTraits<A$(ARG)>::ForwardT ype a$(ARG)]]) {
173 return (object->*method_)($for ARG , [[a$(ARG)]]);
174 }
175
176 private:
177 R (T::*method_)($for ARG , [[A$(ARG)]]) const;
178 };
179
180 ]] $$ for ARITY
181
61 182
62 // FunctionTraits<> 183 // FunctionTraits<>
63 // 184 //
64 // The FunctionTraits<> template determines the type of function, and also 185 // Breaks a function signature apart into typedefs for easier introspection.
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)).
69 //
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.
75 //
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.
82 //
83 // By normalizing the function signature, we reduce function_type to exactly 2.
84
85 template <typename Sig> 186 template <typename Sig>
86 struct FunctionTraits; 187 struct FunctionTraits;
87 188
88 $range ARITY 0..MAX_ARITY 189 $for ARITY [[
89 $for ARITY [[ 190 $range ARG 1..ARITY
90 $range ARG 1..ARITY 191
91
92 // Function: Arity $(ARITY).
93 template <typename R[[]] 192 template <typename R[[]]
94 $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> 193 $if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]>
95 struct FunctionTraits<R(*)($for ARG , [[X$(ARG)]])> { 194 struct FunctionTraits<R($for ARG , [[A$(ARG)]])> {
96 typedef R (*NormalizedSig)($for ARG , [[X$(ARG)]]); 195 typedef R ReturnType;
97 typedef false_type IsMethod; 196 $for ARG [[
98 197
99 typedef R Return; 198 typedef A$(ARG) A$(ARG)Type;
199 ]]
200
201 };
202
203 ]]
204
205
206 // ForceVoidReturn<>
207 //
208 // Set of templates that support forcing the function return type to void.
209 template <typename Sig>
210 struct ForceVoidReturn;
211
212 $for ARITY [[
213 $range ARG 1..ARITY
214
215 template <typename R[[]]
216 $if ARITY > 0[[, ]] $for ARG , [[typename A$(ARG)]]>
217 struct ForceVoidReturn<R($for ARG , [[A$(ARG)]])> {
218 typedef void(RunType)($for ARG , [[A$(ARG)]]);
219 };
220
221 ]] $$ for ARITY
222
223
224 // FunctorTraits<>
225 //
226 // See description at top of file.
227 template <typename T>
228 struct FunctorTraits {
229 typedef RunnableAdapter<T> RunnableType;
230 typedef typename RunnableType::RunType RunType;
231 };
232
233 template <typename T>
234 struct FunctorTraits<IgnoreResultHelper<T> > {
235 typedef typename FunctorTraits<T>::RunnableType RunnableType;
236 typedef typename ForceVoidReturn<
237 typename RunnableType::RunType>::RunType RunType;
238 };
239
240 template <typename T>
241 struct FunctorTraits<Callback<T> > {
242 typedef Callback<T> RunnableType;
243 typedef typename Callback<T>::RunType RunType;
244 };
245
246
247 // MakeRunnable<>
248 //
249 // Converts a passed in functor to a RunnableType using type inference.
250
251 template <typename T>
252 typename FunctorTraits<T>::RunnableType MakeRunnable(const T& t) {
253 return RunnableAdapter<T>(t);
254 }
255
256 template <typename T>
257 typename FunctorTraits<T>::RunnableType
258 MakeRunnable(const IgnoreResultHelper<T>& t) {
259 return MakeRunnable(t.functor_);
260 }
261
262 template <typename T>
263 const typename FunctorTraits<Callback<T> >::RunnableType&
264 MakeRunnable(const Callback<T>& t) {
265 return t;
266 }
267
268
269 // InvokeHelper<>
270 //
271 // There are 3 logical InvokeHelper<> specializations: normal, void-return,
272 // WeakCalls.
273 //
274 // The normal type just calls the underlying runnable.
275 //
276 // We need a InvokeHelper to handle void return types in order to support
277 // IgnoreResult(). Normally, if the Runnable's RunType had a void return,
278 // the template system would just accept "return functor.Run()" ignoring
279 // the fact that a void function is being used with return. This piece of
280 // sugar breaks though when the Runnable's RunType is not void. Thus, we
281 // need a partial specialization to change the syntax to drop the "return"
282 // from the invocation call.
283 //
284 // WeakCalls similarly need special syntax that is applied to the first
285 // argument to check if they should no-op themselves.
286 template <bool IsWeakCall, typename ReturnType, typename Runnable,
287 typename ArgsType>
288 struct InvokeHelper;
289
290 $for ARITY [[
291 $range ARG 1..ARITY
292
293 template <typename ReturnType, typename Runnable[[]]
294 $if ARITY > 0 [[,]] $for ARG , [[typename A$(ARG)]]>
295 struct InvokeHelper<false, ReturnType, Runnable,
296 void($for ARG , [[A$(ARG)]])> {
297 static ReturnType MakeItSo(Runnable runnable[[]]
298 $if ARITY > 0[[, ]] $for ARG , [[A$(ARG) a$(ARG)]]) {
299 return runnable.Run($for ARG , [[a$(ARG)]]);
300 }
301 };
302
303 template <typename Runnable[[]]
304 $if ARITY > 0 [[,]] $for ARG , [[typename A$(ARG)]]>
305 struct InvokeHelper<false, void, Runnable,
306 void($for ARG , [[A$(ARG)]])> {
307 static void MakeItSo(Runnable runnable[[]]
308 $if ARITY > 0[[, ]] $for ARG , [[A$(ARG) a$(ARG)]]) {
309 runnable.Run($for ARG , [[a$(ARG)]]);
310 }
311 };
100 312
101 $if ARITY > 0 [[ 313 $if ARITY > 0 [[
102 314
103 // Target type for each bound parameter. 315 template <typename Runnable[[]], $for ARG , [[typename A$(ARG)]]>
104 316 struct InvokeHelper<true, void, Runnable,
105 $for ARG [[ 317 void($for ARG , [[A$(ARG)]])> {
106 typedef X$(ARG) B$(ARG); 318 static void MakeItSo(Runnable runnable[[]]
107 319 $if ARITY > 0[[, ]] $for ARG , [[A$(ARG) a$(ARG)]]) {
108 ]] $$ for ARG 320 if (!a1.get()) {
109 ]] $$ if ARITY > 0 321 return;
110 322 }
111 }; 323
112 324 runnable.Run($for ARG , [[a$(ARG)]]);
113 // Method: Arity $(ARITY). 325 }
114 template <typename R, typename T[[]] 326 };
115 $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> 327
116 struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]])> { 328 ]]
117 typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]); 329
118 typedef true_type IsMethod; 330 ]] $$ for ARITY
119 331
120 typedef R Return; 332 #if !defined(_MSC_VER)
121 333
122 // Target type for each bound parameter. 334 template <typename ReturnType, typename Runnable, typename ArgsType>
123 typedef T B1; 335 struct InvokeHelper<true, ReturnType, Runnable, ArgsType> {
124 336 // WeakCalls are only supported for functions with a void return type.
125 $for ARG [[ 337 // Otherwise, the function result would be undefined if the the WeakPtr<>
126 typedef X$(ARG) B$(ARG + 1); 338 // is invalidated.
127 339 COMPILE_ASSERT(is_void<ReturnType>::value,
128 ]] $$ for ARG 340 weak_ptrs_can_only_bind_to_methods_without_return_values);
129 341 };
130 }; 342
131 343 #endif
132 // Const Method: Arity $(ARITY). 344
133 template <typename R, typename T[[]] 345 // Invoker<>
134 $if ARITY > 0[[, ]] $for ARG , [[typename X$(ARG)]]> 346 //
135 struct FunctionTraits<R(T::*)($for ARG , [[X$(ARG)]]) const> { 347 // See description at the top of the file.
136 typedef R (T::*NormalizedSig)($for ARG , [[X$(ARG)]]); 348 template <int NumBound, typename Storage, typename RunType>
137 typedef true_type IsMethod; 349 struct Invoker;
138 350
139 typedef R Return; 351 $for ARITY [[
140 352
141 // Target type for each bound parameter. 353 $$ Number of bound arguments.
142 typedef T B1; 354 $range BOUND 0..ARITY
143
144 $for ARG [[
145 typedef X$(ARG) B$(ARG + 1);
146
147 ]] $$ for ARG
148
149 };
150
151 ]] $$for ARITY
152
153 // InvokerN<>
154 //
155 // The InvokerN templates contain a static DoInvoke() function that is the key
156 // to implementing type erasure in the Callback() classes.
157 //
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.
163 //
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.
167 //
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.
172
173 $range BOUND 0..MAX_ARITY
174 $for BOUND [[ 355 $for BOUND [[
175 356
176 template <bool IsWeak, typename StorageType, typename NormalizedSig>
177 struct Invoker$(BOUND);
178
179 $range ARITY 0..MAX_ARITY
180 $for ARITY [[
181
182 $var UNBOUND = ARITY - BOUND 357 $var UNBOUND = ARITY - BOUND
183 $if UNBOUND >= 0 [[
184
185 $$ Variables for function traits generation.
186 $range ARG 1..ARITY 358 $range ARG 1..ARITY
187 $range BOUND_ARG 1..BOUND 359 $range BOUND_ARG 1..BOUND
188 $range UNBOUND_ARG (ARITY - UNBOUND + 1)..ARITY 360 $range UNBOUND_ARG (ARITY - UNBOUND + 1)..ARITY
189 361
190 $$ Variables for method traits generation. We are always short one arity since 362 // Arity $(ARITY) -> $(UNBOUND).
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
196
197 // Function: Arity $(ARITY) -> $(UNBOUND).
198 template <typename StorageType, typename R[[]] 363 template <typename StorageType, typename R[[]]
199 $if ARITY > 0 [[,]][[]] 364 $if ARITY > 0 [[,]][[]]
200 $for ARG , [[typename X$(ARG)]]> 365 $for ARG , [[typename X$(ARG)]]>
201 struct Invoker$(BOUND)<false, StorageType, R(*)($for ARG , [[X$(ARG)]])> { 366 struct Invoker<$(BOUND), StorageType, R($for ARG , [[X$(ARG)]])> {
202 typedef R(*DoInvokeType)( 367 typedef R(RunType)(BindStateBase*[[]]
203 internal::InvokerStorageBase*[[]]
204 $if UNBOUND != 0 [[, ]] 368 $if UNBOUND != 0 [[, ]]
205 $for UNBOUND_ARG , [[typename internal::ParamTraits<X$(UNBOUND_ARG)>::ForwardTyp e]]); 369 $for UNBOUND_ARG , [[typename CallbackParamTraits<X$(UNBOUND_ARG)>::ForwardType] ]);
206 370
207 static R DoInvoke(InvokerStorageBase* base[[]] 371 typedef R(UnboundRunType)($for UNBOUND_ARG , [[X$(UNBOUND_ARG)]]);
372
373 static R Run(BindStateBase* base[[]]
208 $if UNBOUND != 0 [[, ]][[]] 374 $if UNBOUND != 0 [[, ]][[]]
209 $for UNBOUND_ARG , [[typename internal::ParamTraits<X$(UNBOUND_ARG)>::ForwardTyp e x$(UNBOUND_ARG)]]) { 375 $for UNBOUND_ARG , [[
210 StorageType* invoker = static_cast<StorageType*>(base); 376 typename CallbackParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG)
211 return invoker->f_($for BOUND_ARG , [[Unwrap(invoker->p$(BOUND_ARG)_)]][[]] 377 ]][[]]
212 $$ Add comma if there are both boudn and unbound args. 378 ) {
379 StorageType* storage = static_cast<StorageType*>(base);
380
381 // Local references to make debugger stepping easier. If in a debugger,
382 // you really want to warp ahead and step through the
383 // InvokeHelper<>::MakeItSo() call below.
384 $for BOUND_ARG
385 [[
386
387 typedef typename StorageType::Bound$(BOUND_ARG)UnwrapTraits Bound$(BOUND_ARG )UnwrapTraits;
388 ]]
389
390
391 $for BOUND_ARG
392 [[
393
394 typename Bound$(BOUND_ARG)UnwrapTraits::ForwardType x$(BOUND_ARG) =
395 Bound$(BOUND_ARG)UnwrapTraits::Unwrap(storage->p$(BOUND_ARG)_);
396 ]]
397
398 return InvokeHelper<StorageType::IsWeakCall::value, R,
399 typename StorageType::RunnableType,
400 void(
401 $for BOUND_ARG , [[
402 typename Bound$(BOUND_ARG)UnwrapTraits::ForwardType
403 ]]
404
213 $if UNBOUND > 0 [[$if BOUND > 0 [[, ]]]][[]] 405 $if UNBOUND > 0 [[$if BOUND > 0 [[, ]]]][[]]
214 $for UNBOUND_ARG , [[x$(UNBOUND_ARG)]]); 406
215 } 407 $for UNBOUND_ARG , [[
216 }; 408 typename CallbackParamTraits<X$(UNBOUND_ARG)>::ForwardType x$(UNBOUND_ARG)
217 409 ]]
218 $if BOUND > 0 [[ 410 )>
219 411 ::MakeItSo(storage->runnable_
220 // Method: Arity $(M_ARITY) -> $(UNBOUND). 412 $if ARITY > 0[[, ]] $for ARG , [[x$(ARG)]]);
221 template <typename StorageType, typename R, typename T[[]] 413 }
222 $if M_ARITY > 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]> 414 };
223 struct Invoker$(BOUND)<false, StorageType, R(T::*)($for M_ARG , [[X$(M_ARG)]])> { 415
224 typedef R(*DoInvokeType)( 416 ]] $$ for BOUND
225 internal::InvokerStorageBase*[[]] 417 ]] $$ for ARITY
226 $if UNBOUND != 0 [[, ]] 418
227 $for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::Forwar dType]]); 419
228 420 // BindState<>
229 static R DoInvoke(InvokerStorageBase* base[[]] 421 //
230 $if UNBOUND > 0 [[, ]][[]] 422 // This stores all the state passed into Bind() and is also where most
231 $for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::Forwar dType x$(M_UNBOUND_ARG)]]) { 423 // of the template resolution magic occurs.
232 StorageType* invoker = static_cast<StorageType*>(base); 424 //
233 return (Unwrap(invoker->p1_)->*invoker->f_)([[]] 425 // Runnable is the functor we are binding arguments to.
234 $for M_BOUND_ARG , [[Unwrap(invoker->p$(M_BOUND_ARG)_)]][[]] 426 // RunType is type of the Run() function that the Invoker<> should use.
235 $if UNBOUND > 0 [[$if BOUND > 1 [[, ]]]][[]] 427 // Normally, this is the same as the RunType of the Runnable, but it can
236 $for M_UNBOUND_ARG , [[x$(M_UNBOUND_ARG)]]); 428 // be different if an adapter like IgnoreResult() has been used.
237 } 429 //
238 }; 430 // BoundArgsType contains the storage type for all the bound arguments by
239 431 // (ab)using a function type.
240 // WeakPtr Method: Arity $(M_ARITY) -> $(UNBOUND). 432 template <typename Runnable, typename RunType, typename BoundArgsType>
241 template <typename StorageType, typename T[[]] 433 struct BindState;
242 $if M_ARITY > 0[[, ]] $for M_ARG , [[typename X$(M_ARG)]]> 434
243 struct Invoker$(BOUND)<true, StorageType, void(T::*)($for M_ARG , [[X$(M_ARG)]]) > { 435 $for ARITY [[
244 typedef void(*DoInvokeType)( 436 $range ARG 1..ARITY
245 internal::InvokerStorageBase*[[]] 437
246 $if UNBOUND != 0 [[, ]] 438 template <typename Runnable, typename RunType[[]]
247 $for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::Forwar dType]]); 439 $if ARITY > 0[[, ]] $for ARG , [[typename P$(ARG)]]>
248 440 struct BindState<Runnable, RunType, void($for ARG , [[P$(ARG)]])> : public BindS tateBase {
249 static void DoInvoke(InvokerStorageBase* base[[]] 441 typedef Runnable RunnableType;
250 $if UNBOUND > 0 [[, ]][[]] 442
251 $for M_UNBOUND_ARG , [[typename internal::ParamTraits<X$(M_UNBOUND_ARG)>::Forwar dType x$(M_UNBOUND_ARG)]]) { 443 $if ARITY > 0 [[
252 StorageType* invoker = static_cast<StorageType*>(base); 444 typedef IsWeakMethod<HasIsMethodTag<Runnable>::value, P1> IsWeakCall;
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 }
262 };
263
264 ]] $$ if BOUND
265
266 ]] $$ if UNBOUND
267 ]] $$ for ARITY
268 ]] $$ for BOUND
269
270 // BindMoreFuncN<>
271 //
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 [[
277
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)]]);
282 }
283
284 ]] $$ if BOUND
285 ]] $$ for BOUND
286
287 // InvokerStorageN<>
288 //
289 // These are the actual storage classes for the Invokers.
290 //
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().
297 //
298 // An alternate solution would be to merge InvokerN and InvokerStorageN,
299 // but the generated code seemed harder to read.
300
301 $for BOUND [[
302 $range BOUND_ARG 1..BOUND
303
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;
313
314 $for BOUND_ARG [[
315 typedef ParamTraits<P$(BOUND_ARG)> P$(BOUND_ARG)Traits;
316
317 ]]
318
319 $if BOUND == 0 [[
320 typedef Invoker$(BOUND)<false, StorageType,
321 typename TargetTraits::NormalizedSig> Invoker;
322 ]] $else [[ 445 ]] $else [[
323 typedef Invoker$(BOUND)<IsWeakMethod<IsMethod::value, P1>::value, StorageType, 446 typedef false_type IsWeakCall;
324 typename TargetTraits::NormalizedSig> Invoker; 447 ]]
325 COMPILE_ASSERT(!(IsWeakMethod<IsMethod::value, P1>::value) || 448
326 is_void<typename TargetTraits::Return>::value, 449 typedef Invoker<$(ARITY), BindState, RunType> InvokerType;
327 weak_ptrs_can_only_bind_to_methods_without_return_values); 450 typedef typename InvokerType::UnboundRunType UnboundRunType;
328 ]] 451
329 452 $if ARITY > 0 [[
330 453
331 $for BOUND_ARG [[ 454 // Convenience typedefs for bound argument types.
332 $if BOUND_ARG == 1 [[ 455
333 456 $for ARG [[
334 // For methods, we need to be careful for parameter 1. We skip the 457 typedef UnwrapTraits<P$(ARG)> Bound$(ARG)UnwrapTraits;
335 // scoped_refptr check because the binder itself takes care of this. We also 458
336 // disallow binding of an array as the method's target object. 459 ]] $$ for ARG
337 COMPILE_ASSERT(IsMethod::value || 460
338 internal::NeedsScopedRefptrButGetsRawPtr< 461
339 typename ParamTraits<P$(BOUND_ARG)>::StorageType>::value == 0, 462 ]] $$ if ARITY > 0
340 p$(BOUND_ARG)_is_refcounted_type_and_needs_scoped_refptr); 463
341 COMPILE_ASSERT(!IsMethod::value || !is_array<P$(BOUND_ARG)>::value, 464 $$ The extra [[ ]] is needed to massage spacing. Silly pump.py.
342 first_bound_argument_to_method_cannot_be_array); 465 [[ ]]$if ARITY == 0 [[explicit ]]BindState(const Runnable& runnable
466 $if ARITY > 0 [[, ]] $for ARG , [[const P$(ARG)& p$(ARG)]])
467 : runnable_(runnable)[[]]
468 $if ARITY == 0 [[
469 {
470
343 ]] $else [[ 471 ]] $else [[
344 472 , $for ARG , [[
345 COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr< 473
346 typename ParamTraits<P$(BOUND_ARG)>::StorageType>::value == 0, 474 p$(ARG)_(p$(ARG))
347 p$(BOUND_ARG)_is_refcounted_type_and_needs_scoped_refptr); 475 ]] {
348 ]] $$ $if BOUND_ARG 476 MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::AddRef(p1_);
349 ]] $$ $for BOUND_ARG 477
350 478 ]]
351 479 }
352 $if BOUND > 0 [[ 480
353 481 virtual ~BindState() {
354 // Do not allow binding a non-const reference parameter. Non-const reference 482 $if ARITY > 0 [[
355 // parameters are disallowed by the Google style guide. Also, binding a 483 MaybeRefcount<HasIsMethodTag<Runnable>::value, P1>::Release(p1_);
356 // non-const reference parameter can make for subtle bugs because the 484 ]]
357 // invoked function will receive a reference to the stored copy of the 485 }
358 // argument and not the original. 486
359 COMPILE_ASSERT( 487 RunnableType runnable_;
360 !($for BOUND_ARG || [[ is_non_const_reference<typename TargetTraits::B$(BO UND_ARG)>::value ]]), 488
361 do_not_bind_functions_with_nonconst_ref); 489 $for ARG [[
362 490 P$(ARG) p$(ARG)_;
363 ]] 491
364 492 ]]
365 493 };
366 InvokerStorage$(BOUND)(Sig f 494
367 $if BOUND > 0 [[, ]] 495 ]] $$ for ARITY
368 $for BOUND_ARG , [[const P$(BOUND_ARG)& p$(BOUND_ARG)]])
369 : f_(f)[[]]
370 $if BOUND == 0 [[
371 {
372
373 ]] $else [[
374 , $for BOUND_ARG , [[p$(BOUND_ARG)_(static_cast<typename ParamTraits<P$(BOUND_AR G)>::StorageType>(p$(BOUND_ARG)))]] {
375 MaybeRefcount<IsMethod, P1>::AddRef(p1_);
376
377 ]]
378 }
379
380 virtual ~InvokerStorage$(BOUND)() {
381 $if BOUND > 0 [[
382
383 MaybeRefcount<IsMethod, P1>::Release(p1_);
384
385 ]]
386 }
387
388 Sig f_;
389
390 $for BOUND_ARG [[
391 typename ParamTraits<P$(BOUND_ARG)>::StorageType p$(BOUND_ARG)_;
392
393 ]]
394 };
395
396 ]] $$ for BOUND
397 496
398 } // namespace internal 497 } // namespace internal
399 } // namespace base 498 } // namespace base
400 499
401 #endif // BASE_BIND_INTERNAL_H_ 500 #endif // BASE_BIND_INTERNAL_H_
OLDNEW
« no previous file with comments | « base/bind_internal.h ('k') | base/bind_internal_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698