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

Side by Side Diff: base/bind_internal.h

Issue 2106773002: Remove `Runnable` concept from base/bind_internal.h (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase onto clang crash workaround Created 4 years, 5 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
« no previous file with comments | « base/bind_helpers.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 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef BASE_BIND_INTERNAL_H_ 5 #ifndef BASE_BIND_INTERNAL_H_
6 #define BASE_BIND_INTERNAL_H_ 6 #define BASE_BIND_INTERNAL_H_
7 7
8 #include <stddef.h> 8 #include <stddef.h>
9 9
10 #include <tuple> 10 #include <tuple>
11 #include <type_traits> 11 #include <type_traits>
12 12
13 #include "base/bind_helpers.h" 13 #include "base/bind_helpers.h"
14 #include "base/callback_internal.h" 14 #include "base/callback_internal.h"
15 #include "base/memory/raw_scoped_refptr_mismatch_checker.h" 15 #include "base/memory/raw_scoped_refptr_mismatch_checker.h"
16 #include "base/memory/weak_ptr.h" 16 #include "base/memory/weak_ptr.h"
17 #include "base/template_util.h" 17 #include "base/template_util.h"
18 #include "base/tuple.h" 18 #include "base/tuple.h"
19 #include "build/build_config.h" 19 #include "build/build_config.h"
20 20
21 #if defined(OS_WIN)
22 #include "base/bind_internal_win.h"
23 #endif
24
25 namespace base { 21 namespace base {
26 namespace internal { 22 namespace internal {
27 23
28 // See base/callback.h for user documentation. 24 // See base/callback.h for user documentation.
29 // 25 //
30 // 26 //
31 // CONCEPTS: 27 // CONCEPTS:
32 // Runnable -- A type (really a type class) that has a single Run() method 28 // Functor -- A movable type representing something that should be called.
33 // and a RunType typedef that corresponds to the type of Run(). 29 // All function pointers and Callback<> are functors even if the
34 // A Runnable can declare that it should treated like a method 30 // invocation syntax differs.
35 // call by including a typedef named IsMethod. The value of
36 // this typedef is NOT inspected, only the existence. When a
37 // Runnable declares itself a method, Bind() will enforce special
38 // refcounting + WeakPtr handling semantics for the first
39 // parameter which is expected to be an object.
40 // Functor -- A copyable type representing something that should be called.
41 // All function pointers, Callback<>, and Runnables are functors
42 // even if the invocation syntax differs.
43 // RunType -- A function type (as opposed to function _pointer_ type) for 31 // RunType -- A function type (as opposed to function _pointer_ type) for
44 // a Run() function. Usually just a convenience typedef. 32 // a Run() function. Usually just a convenience typedef.
Yuta Kitamura 2016/06/30 07:13:29 Apparently Run() in this context is no more?
tzik 2016/07/01 04:11:00 Changed this to Callback<>::Run().
45 // (Bound)Args -- A set of types that stores the arguments. 33 // (Bound)Args -- A set of types that stores the arguments.
46 // 34 //
47 // Types: 35 // Types:
48 // RunnableAdapter<> -- Wraps the various "function" pointer types into an
49 // object that adheres to the Runnable interface.
50 // ForceVoidReturn<> -- Helper class for translating function signatures to 36 // ForceVoidReturn<> -- Helper class for translating function signatures to
51 // equivalent forms with a "void" return type. 37 // equivalent forms with a "void" return type.
52 // FunctorTraits<> -- Type traits used determine the correct RunType and 38 // FunctorTraits<> -- Type traits used to determine the correct RunType and
53 // RunnableType for a Functor. This is where function 39 // invocation manner for a Functor. This is where function
54 // signature adapters are applied. 40 // signature adapters are applied.
55 // MakeRunnable<> -- Takes a Functor and returns an object in the Runnable 41 // InvokeHelper<> -- Take a Functor + arguments and actully invokes it.
56 // type class that represents the underlying Functor.
57 // InvokeHelper<> -- Take a Runnable + arguments and actully invokes it.
58 // Handle the differing syntaxes needed for WeakPtr<> 42 // Handle the differing syntaxes needed for WeakPtr<>
59 // support, and for ignoring return values. This is separate 43 // support. This is separate from Invoker to avoid creating
60 // from Invoker to avoid creating multiple version of 44 // multiple version of Invoker<>.
61 // Invoker<>. 45 // Invoker<> -- Unwraps the curried parameters and executes the Functor.
62 // Invoker<> -- Unwraps the curried parameters and executes the Runnable.
63 // BindState<> -- Stores the curried parameters, and is the main entry point 46 // BindState<> -- Stores the curried parameters, and is the main entry point
64 // into the Bind() system, doing most of the type resolution. 47 // into the Bind() system.
65 // There are ARITY BindState types.
66 48
67 // HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw 49 // HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw
68 // pointer to a RefCounted type. 50 // pointer to a RefCounted type.
69 // Implementation note: This non-specialized case handles zero-arity case only. 51 // Implementation note: This non-specialized case handles zero-arity case only.
70 // Non-zero-arity cases should be handled by the specialization below. 52 // Non-zero-arity cases should be handled by the specialization below.
71 template <typename... Args> 53 template <typename... Args>
72 struct HasRefCountedTypeAsRawPtr : std::false_type {}; 54 struct HasRefCountedTypeAsRawPtr : std::false_type {};
73 55
74 // Implementation note: Select true_type if the first parameter is a raw pointer 56 // Implementation note: Select true_type if the first parameter is a raw pointer
75 // to a RefCounted type. Otherwise, skip the first parameter and check rest of 57 // to a RefCounted type. Otherwise, skip the first parameter and check rest of
76 // parameters recursively. 58 // parameters recursively.
77 template <typename T, typename... Args> 59 template <typename T, typename... Args>
78 struct HasRefCountedTypeAsRawPtr<T, Args...> 60 struct HasRefCountedTypeAsRawPtr<T, Args...>
79 : std::conditional<NeedsScopedRefptrButGetsRawPtr<T>::value, 61 : std::conditional<NeedsScopedRefptrButGetsRawPtr<T>::value,
80 std::true_type, 62 std::true_type,
81 HasRefCountedTypeAsRawPtr<Args...>>::type {}; 63 HasRefCountedTypeAsRawPtr<Args...>>::type {};
82 64
83 // BindsArrayToFirstArg selects true_type when |is_method| is true and the first
84 // item of |Args| is an array type.
85 // Implementation note: This non-specialized case handles !is_method case and
86 // zero-arity case only. Other cases should be handled by the specialization
87 // below.
88 template <bool is_method, typename... Args>
89 struct BindsArrayToFirstArg : std::false_type {};
90
91 template <typename T, typename... Args>
92 struct BindsArrayToFirstArg<true, T, Args...>
93 : std::is_array<typename std::remove_reference<T>::type> {};
94
95 // HasRefCountedParamAsRawPtr is the same to HasRefCountedTypeAsRawPtr except
96 // when |is_method| is true HasRefCountedParamAsRawPtr skips the first argument.
97 // Implementation note: This non-specialized case handles !is_method case and
98 // zero-arity case only. Other cases should be handled by the specialization
99 // below.
100 template <bool is_method, typename... Args>
101 struct HasRefCountedParamAsRawPtr : HasRefCountedTypeAsRawPtr<Args...> {};
102
103 template <typename T, typename... Args>
104 struct HasRefCountedParamAsRawPtr<true, T, Args...>
105 : HasRefCountedTypeAsRawPtr<Args...> {};
106
107 // RunnableAdapter<>
108 //
109 // The RunnableAdapter<> templates provide a uniform interface for invoking
110 // a function pointer, method pointer, or const method pointer. The adapter
111 // exposes a Run() method with an appropriate signature. Using this wrapper
112 // allows for writing code that supports all three pointer types without
113 // undue repetition. Without it, a lot of code would need to be repeated 3
114 // times.
115 //
116 // For method pointers and const method pointers the first argument to Run()
117 // is considered to be the received of the method. This is similar to STL's
118 // mem_fun().
119 //
120 // This class also exposes a RunType typedef that is the function type of the
121 // Run() function.
122 //
123 // If and only if the wrapper contains a method or const method pointer, an
124 // IsMethod typedef is exposed. The existence of this typedef (NOT the value)
125 // marks that the wrapper should be considered a method wrapper.
126
127 template <typename Functor>
128 class RunnableAdapter;
129
130 // Function.
131 template <typename R, typename... Args>
132 class RunnableAdapter<R(*)(Args...)> {
133 public:
134 // MSVC 2013 doesn't support Type Alias of function types.
135 // Revisit this after we update it to newer version.
136 typedef R RunType(Args...);
137
138 explicit RunnableAdapter(R(*function)(Args...))
139 : function_(function) {
140 }
141
142 template <typename... RunArgs>
143 R Run(RunArgs&&... args) const {
144 return function_(std::forward<RunArgs>(args)...);
145 }
146
147 private:
148 R (*function_)(Args...);
149 };
150
151 // Method.
152 template <typename R, typename T, typename... Args>
153 class RunnableAdapter<R(T::*)(Args...)> {
154 public:
155 // MSVC 2013 doesn't support Type Alias of function types.
156 // Revisit this after we update it to newer version.
157 typedef R RunType(T*, Args...);
158 using IsMethod = std::true_type;
159
160 explicit RunnableAdapter(R(T::*method)(Args...))
161 : method_(method) {
162 }
163
164 template <typename Receiver, typename... RunArgs>
165 R Run(Receiver&& receiver_ptr, RunArgs&&... args) const {
166 // Clang skips CV qualifier check on a method pointer invocation when the
167 // receiver is a subclass. Store the receiver into a const reference to
168 // T to ensure the CV check works.
169 // https://llvm.org/bugs/show_bug.cgi?id=27037
170 T& receiver = *receiver_ptr;
171 return (receiver.*method_)(std::forward<RunArgs>(args)...);
172 }
173
174 private:
175 R (T::*method_)(Args...);
176 };
177
178 // Const Method.
179 template <typename R, typename T, typename... Args>
180 class RunnableAdapter<R(T::*)(Args...) const> {
181 public:
182 using RunType = R(const T*, Args...);
183 using IsMethod = std::true_type;
184
185 explicit RunnableAdapter(R(T::*method)(Args...) const)
186 : method_(method) {
187 }
188
189 template <typename Receiver, typename... RunArgs>
190 R Run(Receiver&& receiver_ptr, RunArgs&&... args) const {
191 // Clang skips CV qualifier check on a method pointer invocation when the
192 // receiver is a subclass. Store the receiver into a unqualified reference
193 // to T to ensure the CV check works.
194 // https://llvm.org/bugs/show_bug.cgi?id=27037
195 const T& receiver = *receiver_ptr;
196 return (receiver.*method_)(std::forward<RunArgs>(args)...);
197 }
198
199 private:
200 R (T::*method_)(Args...) const;
201 };
202
203
204 // ForceVoidReturn<> 65 // ForceVoidReturn<>
205 // 66 //
206 // Set of templates that support forcing the function return type to void. 67 // Set of templates that support forcing the function return type to void.
207 template <typename Sig> 68 template <typename Sig>
208 struct ForceVoidReturn; 69 struct ForceVoidReturn;
209 70
210 template <typename R, typename... Args> 71 template <typename R, typename... Args>
211 struct ForceVoidReturn<R(Args...)> { 72 struct ForceVoidReturn<R(Args...)> {
212 // MSVC 2013 doesn't support Type Alias of function types. 73 using RunType = void(Args...);
213 // Revisit this after we update it to newer version.
214 typedef void RunType(Args...);
215 }; 74 };
216 75
217
218 // FunctorTraits<> 76 // FunctorTraits<>
219 // 77 //
220 // See description at top of file. 78 // See description at top of file.
221 template <typename T> 79 template <typename Functor>
222 struct FunctorTraits { 80 struct FunctorTraits;
223 using RunnableType = RunnableAdapter<T>; 81
224 using RunType = typename RunnableType::RunType; 82 // For functions.
83 template <typename R, typename... Args>
84 struct FunctorTraits<R (*)(Args...)> {
85 using RunType = R(Args...);
86 static constexpr bool is_method = false;
87
88 template <typename... RunArgs>
89 static R Invoke(R (*function)(Args...), RunArgs&&... args) {
90 return function(std::forward<RunArgs>(args)...);
91 }
225 }; 92 };
226 93
227 template <typename T> 94 #if defined(OS_WIN) && !defined(ARCH_CPU_X86_64)
228 struct FunctorTraits<IgnoreResultHelper<T>> { 95
229 using RunnableType = typename FunctorTraits<T>::RunnableType; 96 // For functions.
230 using RunType = 97 template <typename R, typename... Args>
231 typename ForceVoidReturn<typename RunnableType::RunType>::RunType; 98 struct FunctorTraits<R(__stdcall*)(Args...)> {
99 using RunType = R(Args...);
100 static constexpr bool is_method = false;
101
102 template <typename... RunArgs>
103 static R Invoke(R(__stdcall* function)(Args...), RunArgs&&... args) {
104 return function(std::forward<RunArgs>(args)...);
105 }
232 }; 106 };
233 107
234 template <typename T> 108 // For functions.
235 struct FunctorTraits<Callback<T>> { 109 template <typename R, typename... Args>
236 using RunnableType = Callback<T> ; 110 struct FunctorTraits<R(__fastcall*)(Args...)> {
237 using RunType = typename Callback<T>::RunType; 111 using RunType = R(Args...);
112 static constexpr bool is_method = false;
113
114 template <typename... RunArgs>
115 static R Invoke(R(__fastcall* function)(Args...), RunArgs&&... args) {
116 return function(std::forward<RunArgs>(args)...);
117 }
238 }; 118 };
239 119
120 #endif // defined(OS_WIN) && !defined(ARCH_CPU_X86_64)
240 121
241 // MakeRunnable<> 122 // For methods.
242 // 123 template <typename R, typename Receiver, typename... Args>
243 // Converts a passed in functor to a RunnableType using type inference. 124 struct FunctorTraits<R (Receiver::*)(Args...)> {
125 using RunType = R(Receiver*, Args...);
126 static constexpr bool is_method = true;
244 127
128 template <typename ReceiverPtr, typename... RunArgs>
129 static R Invoke(R (Receiver::*method)(Args...),
130 ReceiverPtr&& receiver_ptr,
131 RunArgs&&... args) {
dcheng 2016/06/30 12:53:36 Is the clang CV qualifier check comment in the old
tzik 2016/07/01 04:11:00 Oh, I missed to move it. It's still valid, and NCT
132 Receiver& receiver = *receiver_ptr;
133 return (receiver.*method)(std::forward<RunArgs>(args)...);
134 }
135 };
136
137 // For const methods.
138 template <typename R, typename Receiver, typename... Args>
139 struct FunctorTraits<R (Receiver::*)(Args...) const> {
140 using RunType = R(const Receiver*, Args...);
141 static constexpr bool is_method = true;
142
143 template <typename ReceiverPtr, typename... RunArgs>
144 static R Invoke(R (Receiver::*method)(Args...) const,
145 ReceiverPtr&& receiver_ptr,
146 RunArgs&&... args) {
147 const Receiver& receiver = *receiver_ptr;
148 return (receiver.*method)(std::forward<RunArgs>(args)...);
149 }
150 };
151
152 // For IgnoreResults.
245 template <typename T> 153 template <typename T>
246 typename FunctorTraits<T>::RunnableType MakeRunnable(const T& t) { 154 struct FunctorTraits<IgnoreResultHelper<T>> : FunctorTraits<T> {
247 return RunnableAdapter<T>(t); 155 using RunType =
248 } 156 typename ForceVoidReturn<typename FunctorTraits<T>::RunType>::RunType;
249 157
250 template <typename T> 158 template <typename IgnoreResultType, typename... RunArgs>
251 typename FunctorTraits<T>::RunnableType 159 static void Invoke(IgnoreResultType&& ignore_result_helper,
252 MakeRunnable(const IgnoreResultHelper<T>& t) { 160 RunArgs&&... args) {
253 return MakeRunnable(t.functor_); 161 FunctorTraits<T>::Invoke(ignore_result_helper.functor_,
254 } 162 std::forward<RunArgs>(args)...);
163 }
164 };
255 165
256 template <typename T> 166 // For Callbacks.
257 const typename FunctorTraits<Callback<T>>::RunnableType& 167 template <typename R, typename... Args, CopyMode copy_mode>
258 MakeRunnable(const Callback<T>& t) { 168 struct FunctorTraits<Callback<R(Args...), copy_mode>> {
259 DCHECK(!t.is_null()); 169 using RunType = R(Args...);
260 return t; 170 static constexpr bool is_method = false;
261 } 171
172 template <typename CallbackType, typename... RunArgs>
173 static R Invoke(CallbackType&& callback, RunArgs&&... args) {
174 DCHECK(!callback.is_null());
175 return std::forward<CallbackType>(callback).Run(
176 std::forward<RunArgs>(args)...);
177 }
178 };
262 179
263 180
264 // InvokeHelper<> 181 // InvokeHelper<>
265 // 182 //
266 // There are 3 logical InvokeHelper<> specializations: normal, void-return, 183 // There are 2 logical InvokeHelper<> specializations: normal, WeakCalls.
267 // WeakCalls.
268 // 184 //
269 // The normal type just calls the underlying runnable. 185 // The normal type just calls the underlying runnable.
270 // 186 //
271 // We need a InvokeHelper to handle void return types in order to support 187 // WeakCalls need special syntax that is applied to the first argument to check
272 // IgnoreResult(). Normally, if the Runnable's RunType had a void return, 188 // if they should no-op themselves.
273 // the template system would just accept "return functor.Run()" ignoring
274 // the fact that a void function is being used with return. This piece of
275 // sugar breaks though when the Runnable's RunType is not void. Thus, we
276 // need a partial specialization to change the syntax to drop the "return"
277 // from the invocation call.
278 //
279 // WeakCalls similarly need special syntax that is applied to the first
280 // argument to check if they should no-op themselves.
281 template <bool is_weak_call, typename ReturnType> 189 template <bool is_weak_call, typename ReturnType>
282 struct InvokeHelper; 190 struct InvokeHelper;
283 191
284 template <typename ReturnType> 192 template <typename ReturnType>
285 struct InvokeHelper<false, ReturnType> { 193 struct InvokeHelper<false, ReturnType> {
286 template <typename Runnable, typename... RunArgs> 194 template <typename Functor, typename... RunArgs>
287 static inline ReturnType MakeItSo(Runnable&& runnable, RunArgs&&... args) { 195 static inline ReturnType MakeItSo(Functor&& functor, RunArgs&&... args) {
288 return std::forward<Runnable>(runnable).Run(std::forward<RunArgs>(args)...); 196 using Traits = FunctorTraits<typename std::decay<Functor>::type>;
197 return Traits::Invoke(std::forward<Functor>(functor),
198 std::forward<RunArgs>(args)...);
289 } 199 }
290 }; 200 };
291 201
292 template <>
293 struct InvokeHelper<false, void> {
294 template <typename Runnable, typename... RunArgs>
295 static inline void MakeItSo(Runnable&& runnable, RunArgs&&... args) {
296 std::forward<Runnable>(runnable).Run(std::forward<RunArgs>(args)...);
297 }
298 };
299
300 template <>
301 struct InvokeHelper<true, void> {
302 template <typename Runnable, typename BoundWeakPtr, typename... RunArgs>
303 static void MakeItSo(Runnable&& runnable,
304 BoundWeakPtr&& weak_ptr,
305 RunArgs&&... args) {
306 if (!weak_ptr) {
307 return;
308 }
309 std::forward<Runnable>(runnable).Run(
310 std::forward<BoundWeakPtr>(weak_ptr), std::forward<RunArgs>(args)...);
311 }
312 };
313
314 #if !defined(_MSC_VER)
315
316 template <typename ReturnType> 202 template <typename ReturnType>
317 struct InvokeHelper<true, ReturnType> { 203 struct InvokeHelper<true, ReturnType> {
318 // WeakCalls are only supported for functions with a void return type. 204 // WeakCalls are only supported for functions with a void return type.
319 // Otherwise, the function result would be undefined if the the WeakPtr<> 205 // Otherwise, the function result would be undefined if the the WeakPtr<>
320 // is invalidated. 206 // is invalidated.
321 static_assert(std::is_void<ReturnType>::value, 207 static_assert(std::is_void<ReturnType>::value,
322 "weak_ptrs can only bind to methods without return values"); 208 "weak_ptrs can only bind to methods without return values");
209
210 template <typename Functor, typename BoundWeakPtr, typename... RunArgs>
211 static inline void MakeItSo(Functor&& functor,
212 BoundWeakPtr weak_ptr,
213 RunArgs&&... args) {
214 if (!weak_ptr)
215 return;
216 using Traits = FunctorTraits<typename std::decay<Functor>::type>;
217 Traits::Invoke(std::forward<Functor>(functor),
218 std::forward<BoundWeakPtr>(weak_ptr),
219 std::forward<RunArgs>(args)...);
220 }
323 }; 221 };
324 222
325 #endif
326
327 // Invoker<> 223 // Invoker<>
328 // 224 //
329 // See description at the top of the file. 225 // See description at the top of the file.
330 template <typename StorageType, typename UnboundRunType> 226 template <typename StorageType, typename UnboundRunType>
331 struct Invoker; 227 struct Invoker;
332 228
333 template <typename StorageType, typename R, typename... UnboundArgs> 229 template <typename StorageType, typename R, typename... UnboundArgs>
334 struct Invoker<StorageType, R(UnboundArgs...)> { 230 struct Invoker<StorageType, R(UnboundArgs...)> {
335 static R Run(BindStateBase* base, UnboundArgs&&... unbound_args) { 231 static R Run(BindStateBase* base, UnboundArgs&&... unbound_args) {
336 // Local references to make debugger stepping easier. If in a debugger, 232 // Local references to make debugger stepping easier. If in a debugger,
337 // you really want to warp ahead and step through the 233 // you really want to warp ahead and step through the
338 // InvokeHelper<>::MakeItSo() call below. 234 // InvokeHelper<>::MakeItSo() call below.
339 const StorageType* storage = static_cast<StorageType*>(base); 235 const StorageType* storage = static_cast<StorageType*>(base);
340 static constexpr size_t num_bound_args = 236 static constexpr size_t num_bound_args =
341 std::tuple_size<decltype(storage->bound_args_)>::value; 237 std::tuple_size<decltype(storage->bound_args_)>::value;
342 return RunImpl(storage->runnable_, 238 return RunImpl(storage->functor_,
343 storage->bound_args_, 239 storage->bound_args_,
344 MakeIndexSequence<num_bound_args>(), 240 MakeIndexSequence<num_bound_args>(),
345 std::forward<UnboundArgs>(unbound_args)...); 241 std::forward<UnboundArgs>(unbound_args)...);
346 } 242 }
347 243
348 template <typename Runnable, typename BoundArgsTuple, size_t... indices> 244 private:
349 static inline R RunImpl(Runnable&& runnable, 245 template <typename Functor, typename BoundArgsTuple, size_t... indices>
246 static inline R RunImpl(Functor&& functor,
350 BoundArgsTuple&& bound, 247 BoundArgsTuple&& bound,
Yuta Kitamura 2016/06/30 07:13:29 Both |functor| and |bound| are always lvalue in th
tzik 2016/07/01 04:11:00 Good point. But let me leave this as is for future
351 IndexSequence<indices...>, 248 IndexSequence<indices...>,
352 UnboundArgs&&... unbound_args) { 249 UnboundArgs&&... unbound_args) {
353 static constexpr bool is_method = 250 static constexpr bool is_method =
354 HasIsMethodTag<typename std::decay<Runnable>::type>::value; 251 FunctorTraits<typename std::decay<Functor>::type>::is_method;
355 252
356 using DecayedArgsTuple = typename std::decay<BoundArgsTuple>::type; 253 using DecayedArgsTuple = typename std::decay<BoundArgsTuple>::type;
357 static constexpr bool is_weak_call = 254 static constexpr bool is_weak_call =
358 IsWeakMethod<is_method, 255 IsWeakMethod<is_method,
359 typename std::tuple_element< 256 typename std::tuple_element<
360 indices, 257 indices,
361 DecayedArgsTuple>::type...>::value; 258 DecayedArgsTuple>::type...>::value;
362 259
363 return InvokeHelper<is_weak_call, R>::MakeItSo( 260 return InvokeHelper<is_weak_call, R>::MakeItSo(
364 std::forward<Runnable>(runnable), 261 std::forward<Functor>(functor),
365 Unwrap(std::get<indices>(std::forward<BoundArgsTuple>(bound)))..., 262 Unwrap(base::get<indices>(std::forward<BoundArgsTuple>(bound)))...,
366 std::forward<UnboundArgs>(unbound_args)...); 263 std::forward<UnboundArgs>(unbound_args)...);
367 } 264 }
368 }; 265 };
369 266
370 // Used to implement MakeArgsStorage.
371 template <bool is_method, typename... BoundArgs>
372 struct MakeArgsStorageImpl {
373 using Type = std::tuple<BoundArgs...>;
374 };
375
376 template <typename Obj, typename... BoundArgs>
377 struct MakeArgsStorageImpl<true, Obj*, BoundArgs...> {
378 using Type = std::tuple<scoped_refptr<Obj>, BoundArgs...>;
379 };
380
381 // Constructs a tuple type to store BoundArgs into BindState.
382 // This wraps the first argument into a scoped_refptr if |is_method| is true and
383 // the first argument is a raw pointer.
384 // Other arguments are adjusted for store and packed into a tuple.
385 template <bool is_method, typename... BoundArgs>
386 using MakeArgsStorage = typename MakeArgsStorageImpl<
387 is_method, typename std::decay<BoundArgs>::type...>::Type;
388
389 // Used to implement MakeUnboundRunType. 267 // Used to implement MakeUnboundRunType.
390 template <typename Functor, typename... BoundArgs> 268 template <typename Functor, typename... BoundArgs>
391 struct MakeUnboundRunTypeImpl { 269 struct MakeUnboundRunTypeImpl {
392 using RunType = typename FunctorTraits<Functor>::RunType; 270 using RunType =
271 typename FunctorTraits<typename std::decay<Functor>::type>::RunType;
393 using ReturnType = ExtractReturnType<RunType>; 272 using ReturnType = ExtractReturnType<RunType>;
394 using Args = ExtractArgs<RunType>; 273 using Args = ExtractArgs<RunType>;
395 using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), Args>; 274 using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), Args>;
396 using Type = MakeFunctionType<ReturnType, UnboundArgs>; 275 using Type = MakeFunctionType<ReturnType, UnboundArgs>;
397 }; 276 };
398 277
278
dcheng 2016/06/30 12:53:36 Nit: I think the other top-level definitions in th
tzik 2016/07/01 04:11:00 Done.
399 // BindState<> 279 // BindState<>
400 // 280 //
401 // This stores all the state passed into Bind() and is also where most 281 // This stores all the state passed into Bind().
402 // of the template resolution magic occurs. 282 template <typename Functor, typename... BoundArgs>
403 // 283 struct BindState final : BindStateBase {
404 // Runnable is the functor we are binding arguments to. 284 template <typename... ForwardBoundArgs>
405 // 285 explicit BindState(Functor functor, ForwardBoundArgs&&... bound_args)
406 // BoundArgs contains the storage type for all the bound arguments. 286 : BindStateBase(&Destroy),
407 template <typename Runnable, typename... BoundArgs> 287 functor_(std::move(functor)),
408 struct BindState final : public BindStateBase { 288 bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
409 private: 289 DCHECK(functor_);
410 using RunnableType = typename std::decay<Runnable>::type; 290 }
411 291
412 static constexpr bool is_method = HasIsMethodTag<RunnableType>::value; 292 Functor functor_;
413 293 std::tuple<BoundArgs...> bound_args_;
414 public:
415 template <typename... ForwardArgs>
416 explicit BindState(RunnableType runnable, ForwardArgs&&... bound_args)
417 : BindStateBase(&Destroy),
418 runnable_(std::move(runnable)),
419 bound_args_(std::forward<ForwardArgs>(bound_args)...) {}
420
421 RunnableType runnable_;
422 MakeArgsStorage<is_method, BoundArgs...> bound_args_;
423 294
424 private: 295 private:
425 ~BindState() {} 296 ~BindState() {}
426 297
427 static void Destroy(BindStateBase* self) { 298 static void Destroy(BindStateBase* self) {
428 delete static_cast<BindState*>(self); 299 delete static_cast<BindState*>(self);
429 } 300 }
430 }; 301 };
431 302
303 // Used to implement MakeBindStateType.
304 template <bool is_method, typename Functor, typename... BoundArgs>
305 struct MakeBindStateTypeImpl;
306
307 template <typename Functor, typename... BoundArgs>
308 struct MakeBindStateTypeImpl<false, Functor, BoundArgs...> {
309 static_assert(!HasRefCountedTypeAsRawPtr<BoundArgs...>::value,
310 "A parameter is a refcounted type and needs scoped_refptr.");
311 using Type = BindState<typename std::decay<Functor>::type,
312 typename std::decay<BoundArgs>::type...>;
313 };
314
315 template <typename Functor>
316 struct MakeBindStateTypeImpl<true, Functor> {
317 using Type = BindState<typename std::decay<Functor>::type>;
318 };
319
320 template <typename Functor, typename Receiver, typename... BoundArgs>
321 struct MakeBindStateTypeImpl<true, Functor, Receiver, BoundArgs...> {
322 static_assert(
323 !std::is_array<typename std::remove_reference<Receiver>::type>::value,
324 "First bound argument to a method cannot be an array.");
325 static_assert(!HasRefCountedTypeAsRawPtr<BoundArgs...>::value,
326 "A parameter is a refcounted type and needs scoped_refptr.");
327
328 private:
329 using DecayedReceiver = typename std::decay<Receiver>::type;
330
331 public:
332 using Type = BindState<
333 typename std::decay<Functor>::type,
334 typename std::conditional<
335 std::is_pointer<DecayedReceiver>::value,
336 scoped_refptr<typename std::remove_pointer<DecayedReceiver>::type>,
337 DecayedReceiver>::type,
338 typename std::decay<BoundArgs>::type...>;
339 };
340
341 template <typename Functor, typename... BoundArgs>
342 using MakeBindStateType = typename MakeBindStateTypeImpl<
343 FunctorTraits<typename std::decay<Functor>::type>::is_method,
344 Functor,
345 BoundArgs...>::Type;
346
432 } // namespace internal 347 } // namespace internal
433 348
434 // Returns a RunType of bound functor. 349 // Returns a RunType of bound functor.
435 // E.g. MakeUnboundRunType<R(A, B, C), A, B> is evaluated to R(C). 350 // E.g. MakeUnboundRunType<R(A, B, C), A, B> is evaluated to R(C).
436 template <typename Functor, typename... BoundArgs> 351 template <typename Functor, typename... BoundArgs>
437 using MakeUnboundRunType = 352 using MakeUnboundRunType =
438 typename internal::MakeUnboundRunTypeImpl<Functor, BoundArgs...>::Type; 353 typename internal::MakeUnboundRunTypeImpl<Functor, BoundArgs...>::Type;
439 354
440 } // namespace base 355 } // namespace base
441 356
442 #endif // BASE_BIND_INTERNAL_H_ 357 #endif // BASE_BIND_INTERNAL_H_
OLDNEW
« no previous file with comments | « base/bind_helpers.h ('k') | base/bind_internal_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698