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

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

Issue 7015064: Support binding WeakPtr<> to methods with void return types. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix a few comments. Created 9 years, 7 months 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 $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
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
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
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_
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