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

Side by Side Diff: base/bind_internal.h

Issue 1798403002: Support rvalue-reference Runnables in base::Bind internals (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: s/IsWeakCall/is_weak_call/. Perfect Forwarding -> pass-by-value + std::move() Created 4 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
« no previous file with comments | « no previous file | no next file » | 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 <type_traits> 10 #include <type_traits>
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 // We need a InvokeHelper to handle void return types in order to support 286 // We need a InvokeHelper to handle void return types in order to support
287 // IgnoreResult(). Normally, if the Runnable's RunType had a void return, 287 // IgnoreResult(). Normally, if the Runnable's RunType had a void return,
288 // the template system would just accept "return functor.Run()" ignoring 288 // the template system would just accept "return functor.Run()" ignoring
289 // the fact that a void function is being used with return. This piece of 289 // the fact that a void function is being used with return. This piece of
290 // sugar breaks though when the Runnable's RunType is not void. Thus, we 290 // sugar breaks though when the Runnable's RunType is not void. Thus, we
291 // need a partial specialization to change the syntax to drop the "return" 291 // need a partial specialization to change the syntax to drop the "return"
292 // from the invocation call. 292 // from the invocation call.
293 // 293 //
294 // WeakCalls similarly need special syntax that is applied to the first 294 // WeakCalls similarly need special syntax that is applied to the first
295 // argument to check if they should no-op themselves. 295 // argument to check if they should no-op themselves.
296 template <bool IsWeakCall, typename ReturnType, typename Runnable> 296 template <bool is_weak_call, typename ReturnType>
297 struct InvokeHelper; 297 struct InvokeHelper;
298 298
299 template <typename ReturnType, typename Runnable> 299 template <typename ReturnType>
300 struct InvokeHelper<false, ReturnType, Runnable> { 300 struct InvokeHelper<false, ReturnType> {
301 template <typename... RunArgs> 301 template <typename Runnable, typename... RunArgs>
302 static ReturnType MakeItSo(Runnable runnable, RunArgs&&... args) { 302 static ReturnType MakeItSo(Runnable&& runnable, RunArgs&&... args) {
303 return runnable.Run(std::forward<RunArgs>(args)...); 303 return std::forward<Runnable>(runnable).Run(std::forward<RunArgs>(args)...);
304 } 304 }
305 }; 305 };
306 306
307 template <typename Runnable> 307 template <>
308 struct InvokeHelper<false, void, Runnable> { 308 struct InvokeHelper<false, void> {
309 template <typename... RunArgs> 309 template <typename Runnable, typename... RunArgs>
310 static void MakeItSo(Runnable runnable, RunArgs&&... args) { 310 static void MakeItSo(Runnable&& runnable, RunArgs&&... args) {
311 runnable.Run(std::forward<RunArgs>(args)...); 311 std::forward<Runnable>(runnable).Run(std::forward<RunArgs>(args)...);
312 } 312 }
313 }; 313 };
314 314
315 template <typename Runnable> 315 template <>
316 struct InvokeHelper<true, void, Runnable> { 316 struct InvokeHelper<true, void> {
317 template <typename BoundWeakPtr, typename... RunArgs> 317 template <typename Runnable, typename BoundWeakPtr, typename... RunArgs>
318 static void MakeItSo(Runnable runnable, 318 static void MakeItSo(Runnable&& runnable,
319 BoundWeakPtr weak_ptr, 319 BoundWeakPtr weak_ptr,
320 RunArgs&&... args) { 320 RunArgs&&... args) {
321 if (!weak_ptr.get()) { 321 if (!weak_ptr.get()) {
322 return; 322 return;
323 } 323 }
324 runnable.Run(weak_ptr.get(), std::forward<RunArgs>(args)...); 324 std::forward<Runnable>(runnable).Run(
325 weak_ptr.get(), std::forward<RunArgs>(args)...);
325 } 326 }
326 }; 327 };
327 328
328 #if !defined(_MSC_VER) 329 #if !defined(_MSC_VER)
329 330
330 template <typename ReturnType, typename Runnable> 331 template <typename ReturnType>
331 struct InvokeHelper<true, ReturnType, Runnable> { 332 struct InvokeHelper<true, ReturnType> {
332 // WeakCalls are only supported for functions with a void return type. 333 // WeakCalls are only supported for functions with a void return type.
333 // Otherwise, the function result would be undefined if the the WeakPtr<> 334 // Otherwise, the function result would be undefined if the the WeakPtr<>
334 // is invalidated. 335 // is invalidated.
335 static_assert(std::is_void<ReturnType>::value, 336 static_assert(std::is_void<ReturnType>::value,
336 "weak_ptrs can only bind to methods without return values"); 337 "weak_ptrs can only bind to methods without return values");
337 }; 338 };
338 339
339 #endif 340 #endif
340 341
341 // Invoker<> 342 // Invoker<>
342 // 343 //
343 // See description at the top of the file. 344 // See description at the top of the file.
344 template <typename BoundIndices, typename StorageType, 345 template <typename BoundIndices, typename StorageType,
345 typename InvokeHelperType, typename UnboundForwardRunType> 346 bool is_weak_call, typename UnboundForwardRunType>
346 struct Invoker; 347 struct Invoker;
347 348
348 template <size_t... bound_indices, 349 template <size_t... bound_indices,
349 typename StorageType, 350 typename StorageType,
350 typename InvokeHelperType, 351 bool is_weak_call,
351 typename R, 352 typename R,
352 typename... UnboundArgs> 353 typename... UnboundArgs>
353 struct Invoker<IndexSequence<bound_indices...>, 354 struct Invoker<IndexSequence<bound_indices...>,
354 StorageType, 355 StorageType,
355 InvokeHelperType, 356 is_weak_call,
356 R(UnboundArgs...)> { 357 R(UnboundArgs...)> {
357 static R Run(BindStateBase* base, UnboundArgs&&... unbound_args) { 358 static R Run(BindStateBase* base, UnboundArgs&&... unbound_args) {
358 StorageType* storage = static_cast<StorageType*>(base); 359 StorageType* storage = static_cast<StorageType*>(base);
359 // Local references to make debugger stepping easier. If in a debugger, 360 // Local references to make debugger stepping easier. If in a debugger,
360 // you really want to warp ahead and step through the 361 // you really want to warp ahead and step through the
361 // InvokeHelper<>::MakeItSo() call below. 362 // InvokeHelper<>::MakeItSo() call below.
362 return InvokeHelperType::MakeItSo( 363 return InvokeHelper<is_weak_call, R>::MakeItSo(
363 storage->runnable_, Unwrap(get<bound_indices>(storage->bound_args_))..., 364 storage->runnable_, Unwrap(get<bound_indices>(storage->bound_args_))...,
364 std::forward<UnboundArgs>(unbound_args)...); 365 std::forward<UnboundArgs>(unbound_args)...);
365 } 366 }
366 }; 367 };
367 368
368 // Used to implement MakeArgsStorage. 369 // Used to implement MakeArgsStorage.
369 template <bool is_method, typename... BoundArgs> 370 template <bool is_method, typename... BoundArgs>
370 struct MakeArgsStorageImpl { 371 struct MakeArgsStorageImpl {
371 using Type = std::tuple<BoundArgs...>; 372 using Type = std::tuple<BoundArgs...>;
372 }; 373 };
(...skipping 26 matching lines...) Expand all
399 struct BindState; 400 struct BindState;
400 401
401 template <typename Runnable, 402 template <typename Runnable,
402 typename R, 403 typename R,
403 typename... Args, 404 typename... Args,
404 typename... BoundArgs> 405 typename... BoundArgs>
405 struct BindState<Runnable, R(Args...), BoundArgs...> final 406 struct BindState<Runnable, R(Args...), BoundArgs...> final
406 : public BindStateBase { 407 : public BindStateBase {
407 private: 408 private:
408 using StorageType = BindState<Runnable, R(Args...), BoundArgs...>; 409 using StorageType = BindState<Runnable, R(Args...), BoundArgs...>;
409 using RunnableType = Runnable; 410 using RunnableType = typename std::decay<Runnable>::type;
410 411
411 enum { is_method = HasIsMethodTag<Runnable>::value }; 412 enum { is_method = HasIsMethodTag<RunnableType>::value };
412 413 enum { is_weak_call = IsWeakMethod<
413 // true_type if Runnable is a method invocation and the first bound argument 414 is_method, typename std::decay<BoundArgs>::type...>::value};
414 // is a WeakPtr.
415 using IsWeakCall =
416 IsWeakMethod<is_method, typename std::decay<BoundArgs>::type...>;
417 415
418 using BoundIndices = MakeIndexSequence<sizeof...(BoundArgs)>; 416 using BoundIndices = MakeIndexSequence<sizeof...(BoundArgs)>;
419 using InvokeHelperType = InvokeHelper<IsWeakCall::value, R, Runnable>;
420
421 using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), TypeList<Args...>>; 417 using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), TypeList<Args...>>;
422 418
423 public: 419 public:
424 using UnboundRunType = MakeFunctionType<R, UnboundArgs>; 420 using UnboundRunType = MakeFunctionType<R, UnboundArgs>;
425 using InvokerType = 421 using InvokerType =
426 Invoker<BoundIndices, StorageType, InvokeHelperType, UnboundRunType>; 422 Invoker<BoundIndices, StorageType, is_weak_call, UnboundRunType>;
427 423
428 template <typename... ForwardArgs> 424 template <typename... ForwardArgs>
429 BindState(const Runnable& runnable, ForwardArgs&&... bound_args) 425 BindState(RunnableType runnable, ForwardArgs&&... bound_args)
430 : BindStateBase(&Destroy), 426 : BindStateBase(&Destroy),
431 runnable_(runnable), 427 runnable_(std::move(runnable)),
432 bound_args_(std::forward<ForwardArgs>(bound_args)...) {} 428 bound_args_(std::forward<ForwardArgs>(bound_args)...) {}
433 429
434 RunnableType runnable_; 430 RunnableType runnable_;
435 MakeArgsStorage<is_method, BoundArgs...> bound_args_; 431 MakeArgsStorage<is_method, BoundArgs...> bound_args_;
436 432
437 private: 433 private:
438 ~BindState() {} 434 ~BindState() {}
439 435
440 static void Destroy(BindStateBase* self) { 436 static void Destroy(BindStateBase* self) {
441 delete static_cast<BindState*>(self); 437 delete static_cast<BindState*>(self);
442 } 438 }
443 }; 439 };
444 440
445 } // namespace internal 441 } // namespace internal
446 } // namespace base 442 } // namespace base
447 443
448 #endif // BASE_BIND_INTERNAL_H_ 444 #endif // BASE_BIND_INTERNAL_H_
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698