blob: 4b95f58ab872ba90bccde256da6c54ce948b4167 [file] [log] [blame]
[email protected]b38d3572011-02-15 01:27:381// 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
3// found in the LICENSE file.
4
5#ifndef BASE_BIND_INTERNAL_H_
6#define BASE_BIND_INTERNAL_H_
[email protected]b38d3572011-02-15 01:27:387
avi9b6f42932015-12-26 22:15:148#include <stddef.h>
9
vmpstrc52317f2015-11-18 08:43:2610#include <type_traits>
Jeremy Roman84956fa2017-08-16 15:55:2011#include <utility>
vmpstrc52317f2015-11-18 08:43:2612
[email protected]59eff912011-02-18 23:29:3113#include "base/callback_internal.h"
Sylvain Defresneec3270c2018-05-31 17:19:1514#include "base/compiler_specific.h"
[email protected]8217d4542011-10-01 06:31:4115#include "base/memory/raw_scoped_refptr_mismatch_checker.h"
[email protected]93540582011-05-16 22:35:1416#include "base/memory/weak_ptr.h"
[email protected]b38d3572011-02-15 01:27:3817#include "base/template_util.h"
[email protected]054ac7542011-02-27 01:25:5918#include "build/build_config.h"
19
Sylvain Defresneec3270c2018-05-31 17:19:1520#if defined(OS_MACOSX) && !HAS_FEATURE(objc_arc)
21#include "base/mac/scoped_block.h"
22#endif
23
[email protected]24292642012-07-12 20:06:4024// See base/callback.h for user documentation.
25//
26//
[email protected]7296f2762011-11-21 19:23:4427// CONCEPTS:
tzik99de02b2016-07-01 05:54:1228// Functor -- A movable type representing something that should be called.
29// All function pointers and Callback<> are functors even if the
30// invocation syntax differs.
[email protected]7296f2762011-11-21 19:23:4431// RunType -- A function type (as opposed to function _pointer_ type) for
tzik99de02b2016-07-01 05:54:1232// a Callback<>::Run(). Usually just a convenience typedef.
tzikce3ecf82015-12-15 06:41:4933// (Bound)Args -- A set of types that stores the arguments.
[email protected]b38d3572011-02-15 01:27:3834//
[email protected]7296f2762011-11-21 19:23:4435// Types:
[email protected]7296f2762011-11-21 19:23:4436// ForceVoidReturn<> -- Helper class for translating function signatures to
37// equivalent forms with a "void" return type.
tzik99de02b2016-07-01 05:54:1238// FunctorTraits<> -- Type traits used to determine the correct RunType and
39// invocation manner for a Functor. This is where function
[email protected]7296f2762011-11-21 19:23:4440// signature adapters are applied.
tzik99de02b2016-07-01 05:54:1241// InvokeHelper<> -- Take a Functor + arguments and actully invokes it.
tzik8ce65702015-02-05 19:11:2642// Handle the differing syntaxes needed for WeakPtr<>
tzik99de02b2016-07-01 05:54:1243// support. This is separate from Invoker to avoid creating
44// multiple version of Invoker<>.
45// Invoker<> -- Unwraps the curried parameters and executes the Functor.
[email protected]7296f2762011-11-21 19:23:4446// BindState<> -- Stores the curried parameters, and is the main entry point
tzik99de02b2016-07-01 05:54:1247// into the Bind() system.
[email protected]4346ef912011-02-19 00:52:1548
Peter Kastinga85265e32018-02-15 08:30:2349namespace base {
50
51template <typename T>
52struct IsWeakReceiver;
53
54template <typename>
55struct BindUnwrapTraits;
56
57template <typename Functor, typename BoundArgsTuple, typename SFINAE = void>
58struct CallbackCancellationTraits;
59
60namespace internal {
61
62template <typename Functor, typename SFINAE = void>
63struct FunctorTraits;
64
65template <typename T>
66class UnretainedWrapper {
67 public:
68 explicit UnretainedWrapper(T* o) : ptr_(o) {}
69 T* get() const { return ptr_; }
70
71 private:
72 T* ptr_;
73};
74
75template <typename T>
76class ConstRefWrapper {
77 public:
78 explicit ConstRefWrapper(const T& o) : ptr_(&o) {}
79 const T& get() const { return *ptr_; }
80
81 private:
82 const T* ptr_;
83};
84
85template <typename T>
86class RetainedRefWrapper {
87 public:
88 explicit RetainedRefWrapper(T* o) : ptr_(o) {}
89 explicit RetainedRefWrapper(scoped_refptr<T> o) : ptr_(std::move(o)) {}
90 T* get() const { return ptr_.get(); }
91
92 private:
93 scoped_refptr<T> ptr_;
94};
95
96template <typename T>
97struct IgnoreResultHelper {
98 explicit IgnoreResultHelper(T functor) : functor_(std::move(functor)) {}
99 explicit operator bool() const { return !!functor_; }
100
101 T functor_;
102};
103
104// An alternate implementation is to avoid the destructive copy, and instead
105// specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to
106// a class that is essentially a std::unique_ptr<>.
107//
108// The current implementation has the benefit though of leaving ParamTraits<>
109// fully in callback_internal.h as well as avoiding type conversions during
110// storage.
111template <typename T>
112class OwnedWrapper {
113 public:
114 explicit OwnedWrapper(T* o) : ptr_(o) {}
115 ~OwnedWrapper() { delete ptr_; }
116 T* get() const { return ptr_; }
117 OwnedWrapper(OwnedWrapper&& other) {
118 ptr_ = other.ptr_;
119 other.ptr_ = NULL;
120 }
121
122 private:
123 mutable T* ptr_;
124};
125
126// PassedWrapper is a copyable adapter for a scoper that ignores const.
127//
128// It is needed to get around the fact that Bind() takes a const reference to
129// all its arguments. Because Bind() takes a const reference to avoid
130// unnecessary copies, it is incompatible with movable-but-not-copyable
131// types; doing a destructive "move" of the type into Bind() would violate
132// the const correctness.
133//
134// This conundrum cannot be solved without either C++11 rvalue references or
135// a O(2^n) blowup of Bind() templates to handle each combination of regular
136// types and movable-but-not-copyable types. Thus we introduce a wrapper type
137// that is copyable to transmit the correct type information down into
138// BindState<>. Ignoring const in this type makes sense because it is only
139// created when we are explicitly trying to do a destructive move.
140//
141// Two notes:
142// 1) PassedWrapper supports any type that has a move constructor, however
143// the type will need to be specifically whitelisted in order for it to be
144// bound to a Callback. We guard this explicitly at the call of Passed()
145// to make for clear errors. Things not given to Passed() will be forwarded
146// and stored by value which will not work for general move-only types.
147// 2) is_valid_ is distinct from NULL because it is valid to bind a "NULL"
148// scoper to a Callback and allow the Callback to execute once.
149template <typename T>
150class PassedWrapper {
151 public:
152 explicit PassedWrapper(T&& scoper)
153 : is_valid_(true), scoper_(std::move(scoper)) {}
154 PassedWrapper(PassedWrapper&& other)
155 : is_valid_(other.is_valid_), scoper_(std::move(other.scoper_)) {}
156 T Take() const {
157 CHECK(is_valid_);
158 is_valid_ = false;
159 return std::move(scoper_);
160 }
161
162 private:
163 mutable bool is_valid_;
164 mutable T scoper_;
165};
166
167template <typename T>
168using Unwrapper = BindUnwrapTraits<std::decay_t<T>>;
169
170template <typename T>
Peter Kastingc2f8749bf2018-03-31 03:32:37171decltype(auto) Unwrap(T&& o) {
Peter Kastinga85265e32018-02-15 08:30:23172 return Unwrapper<T>::Unwrap(std::forward<T>(o));
173}
174
175// IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a
176// method. It is used internally by Bind() to select the correct
177// InvokeHelper that will no-op itself in the event the WeakPtr<> for
178// the target object is invalidated.
179//
180// The first argument should be the type of the object that will be received by
181// the method.
182template <bool is_method, typename... Args>
183struct IsWeakMethod : std::false_type {};
184
185template <typename T, typename... Args>
186struct IsWeakMethod<true, T, Args...> : IsWeakReceiver<T> {};
187
188// Packs a list of types to hold them in a single type.
189template <typename... Types>
190struct TypeList {};
191
192// Used for DropTypeListItem implementation.
193template <size_t n, typename List>
194struct DropTypeListItemImpl;
195
196// Do not use enable_if and SFINAE here to avoid MSVC2013 compile failure.
197template <size_t n, typename T, typename... List>
198struct DropTypeListItemImpl<n, TypeList<T, List...>>
199 : DropTypeListItemImpl<n - 1, TypeList<List...>> {};
200
201template <typename T, typename... List>
202struct DropTypeListItemImpl<0, TypeList<T, List...>> {
203 using Type = TypeList<T, List...>;
204};
205
206template <>
207struct DropTypeListItemImpl<0, TypeList<>> {
208 using Type = TypeList<>;
209};
210
211// A type-level function that drops |n| list item from given TypeList.
212template <size_t n, typename List>
213using DropTypeListItem = typename DropTypeListItemImpl<n, List>::Type;
214
215// Used for TakeTypeListItem implementation.
216template <size_t n, typename List, typename... Accum>
217struct TakeTypeListItemImpl;
218
219// Do not use enable_if and SFINAE here to avoid MSVC2013 compile failure.
220template <size_t n, typename T, typename... List, typename... Accum>
221struct TakeTypeListItemImpl<n, TypeList<T, List...>, Accum...>
222 : TakeTypeListItemImpl<n - 1, TypeList<List...>, Accum..., T> {};
223
224template <typename T, typename... List, typename... Accum>
225struct TakeTypeListItemImpl<0, TypeList<T, List...>, Accum...> {
226 using Type = TypeList<Accum...>;
227};
228
229template <typename... Accum>
230struct TakeTypeListItemImpl<0, TypeList<>, Accum...> {
231 using Type = TypeList<Accum...>;
232};
233
234// A type-level function that takes first |n| list item from given TypeList.
235// E.g. TakeTypeListItem<3, TypeList<A, B, C, D>> is evaluated to
236// TypeList<A, B, C>.
237template <size_t n, typename List>
238using TakeTypeListItem = typename TakeTypeListItemImpl<n, List>::Type;
239
240// Used for ConcatTypeLists implementation.
241template <typename List1, typename List2>
242struct ConcatTypeListsImpl;
243
244template <typename... Types1, typename... Types2>
245struct ConcatTypeListsImpl<TypeList<Types1...>, TypeList<Types2...>> {
246 using Type = TypeList<Types1..., Types2...>;
247};
248
249// A type-level function that concats two TypeLists.
250template <typename List1, typename List2>
251using ConcatTypeLists = typename ConcatTypeListsImpl<List1, List2>::Type;
252
253// Used for MakeFunctionType implementation.
254template <typename R, typename ArgList>
255struct MakeFunctionTypeImpl;
256
257template <typename R, typename... Args>
258struct MakeFunctionTypeImpl<R, TypeList<Args...>> {
259 // MSVC 2013 doesn't support Type Alias of function types.
260 // Revisit this after we update it to newer version.
261 typedef R Type(Args...);
262};
263
264// A type-level function that constructs a function type that has |R| as its
265// return type and has TypeLists items as its arguments.
266template <typename R, typename ArgList>
267using MakeFunctionType = typename MakeFunctionTypeImpl<R, ArgList>::Type;
268
269// Used for ExtractArgs and ExtractReturnType.
270template <typename Signature>
271struct ExtractArgsImpl;
272
273template <typename R, typename... Args>
274struct ExtractArgsImpl<R(Args...)> {
275 using ReturnType = R;
276 using ArgsList = TypeList<Args...>;
277};
278
279// A type-level function that extracts function arguments into a TypeList.
280// E.g. ExtractArgs<R(A, B, C)> is evaluated to TypeList<A, B, C>.
281template <typename Signature>
282using ExtractArgs = typename ExtractArgsImpl<Signature>::ArgsList;
283
284// A type-level function that extracts the return type of a function.
285// E.g. ExtractReturnType<R(A, B, C)> is evaluated to R.
286template <typename Signature>
287using ExtractReturnType = typename ExtractArgsImpl<Signature>::ReturnType;
288
tzikc1db72652016-07-08 09:42:38289template <typename Callable,
290 typename Signature = decltype(&Callable::operator())>
291struct ExtractCallableRunTypeImpl;
292
293template <typename Callable, typename R, typename... Args>
tzikf98654b2017-12-02 03:28:58294struct ExtractCallableRunTypeImpl<Callable, R (Callable::*)(Args...)> {
295 using Type = R(Args...);
296};
297
298template <typename Callable, typename R, typename... Args>
299struct ExtractCallableRunTypeImpl<Callable, R (Callable::*)(Args...) const> {
tzikc1db72652016-07-08 09:42:38300 using Type = R(Args...);
301};
302
303// Evaluated to RunType of the given callable type.
304// Example:
305// auto f = [](int, char*) { return 0.1; };
306// ExtractCallableRunType<decltype(f)>
307// is evaluated to
308// double(int, char*);
309template <typename Callable>
310using ExtractCallableRunType =
311 typename ExtractCallableRunTypeImpl<Callable>::Type;
312
tzikf98654b2017-12-02 03:28:58313// IsCallableObject<Functor> is std::true_type if |Functor| has operator().
314// Otherwise, it's std::false_type.
tzikc1db72652016-07-08 09:42:38315// Example:
tzikf98654b2017-12-02 03:28:58316// IsCallableObject<void(*)()>::value is false.
tzikc1db72652016-07-08 09:42:38317//
318// struct Foo {};
tzikf98654b2017-12-02 03:28:58319// IsCallableObject<void(Foo::*)()>::value is false.
tzikc1db72652016-07-08 09:42:38320//
321// int i = 0;
tzikf98654b2017-12-02 03:28:58322// auto f = [i]() {};
323// IsCallableObject<decltype(f)>::value is false.
tzikc1db72652016-07-08 09:42:38324template <typename Functor, typename SFINAE = void>
tzikf98654b2017-12-02 03:28:58325struct IsCallableObject : std::false_type {};
tzikc1db72652016-07-08 09:42:38326
327template <typename Callable>
tzikf98654b2017-12-02 03:28:58328struct IsCallableObject<Callable, void_t<decltype(&Callable::operator())>>
329 : std::true_type {};
tzikc1db72652016-07-08 09:42:38330
tzik401dd3672014-11-26 07:54:58331// HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw
332// pointer to a RefCounted type.
333// Implementation note: This non-specialized case handles zero-arity case only.
334// Non-zero-arity cases should be handled by the specialization below.
335template <typename... Args>
tzik403cb6c2016-03-10 07:17:25336struct HasRefCountedTypeAsRawPtr : std::false_type {};
tzik401dd3672014-11-26 07:54:58337
338// Implementation note: Select true_type if the first parameter is a raw pointer
339// to a RefCounted type. Otherwise, skip the first parameter and check rest of
340// parameters recursively.
341template <typename T, typename... Args>
342struct HasRefCountedTypeAsRawPtr<T, Args...>
Jeremy Roman35a317432017-08-16 22:20:53343 : std::conditional_t<NeedsScopedRefptrButGetsRawPtr<T>::value,
344 std::true_type,
345 HasRefCountedTypeAsRawPtr<Args...>> {};
tzik401dd3672014-11-26 07:54:58346
[email protected]7296f2762011-11-21 19:23:44347// ForceVoidReturn<>
348//
349// Set of templates that support forcing the function return type to void.
350template <typename Sig>
351struct ForceVoidReturn;
352
tzikc82149922014-11-20 10:09:45353template <typename R, typename... Args>
354struct ForceVoidReturn<R(Args...)> {
tzik99de02b2016-07-01 05:54:12355 using RunType = void(Args...);
[email protected]fccef1552011-11-28 22:13:54356};
357
[email protected]7296f2762011-11-21 19:23:44358// FunctorTraits<>
359//
360// See description at top of file.
tzik6c92eab2016-11-25 15:56:36361template <typename Functor, typename SFINAE>
tzik99de02b2016-07-01 05:54:12362struct FunctorTraits;
363
tzikf98654b2017-12-02 03:28:58364// For empty callable types.
tzikc1db72652016-07-08 09:42:38365// This specialization is intended to allow binding captureless lambdas by
tzikf98654b2017-12-02 03:28:58366// base::Bind(), based on the fact that captureless lambdas are empty while
367// capturing lambdas are not. This also allows any functors as far as it's an
368// empty class.
369// Example:
370//
371// // Captureless lambdas are allowed.
372// []() {return 42;};
373//
374// // Capturing lambdas are *not* allowed.
375// int x;
376// [x]() {return x;};
377//
378// // Any empty class with operator() is allowed.
379// struct Foo {
380// void operator()() const {}
381// // No non-static member variable and no virtual functions.
382// };
tzikc1db72652016-07-08 09:42:38383template <typename Functor>
Jeremy Roman35a317432017-08-16 22:20:53384struct FunctorTraits<Functor,
tzikf98654b2017-12-02 03:28:58385 std::enable_if_t<IsCallableObject<Functor>::value &&
386 std::is_empty<Functor>::value>> {
tzikc1db72652016-07-08 09:42:38387 using RunType = ExtractCallableRunType<Functor>;
388 static constexpr bool is_method = false;
389 static constexpr bool is_nullable = false;
390
tzikf98654b2017-12-02 03:28:58391 template <typename RunFunctor, typename... RunArgs>
392 static ExtractReturnType<RunType> Invoke(RunFunctor&& functor,
393 RunArgs&&... args) {
394 return std::forward<RunFunctor>(functor)(std::forward<RunArgs>(args)...);
tzikc1db72652016-07-08 09:42:38395 }
396};
397
tzik99de02b2016-07-01 05:54:12398// For functions.
399template <typename R, typename... Args>
400struct FunctorTraits<R (*)(Args...)> {
401 using RunType = R(Args...);
402 static constexpr bool is_method = false;
tzikc1db72652016-07-08 09:42:38403 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12404
tzikd58a89232018-04-26 04:29:53405 template <typename Function, typename... RunArgs>
406 static R Invoke(Function&& function, RunArgs&&... args) {
407 return std::forward<Function>(function)(std::forward<RunArgs>(args)...);
tzik99de02b2016-07-01 05:54:12408 }
[email protected]7296f2762011-11-21 19:23:44409};
410
tzik99de02b2016-07-01 05:54:12411#if defined(OS_WIN) && !defined(ARCH_CPU_X86_64)
412
413// For functions.
414template <typename R, typename... Args>
415struct FunctorTraits<R(__stdcall*)(Args...)> {
416 using RunType = R(Args...);
417 static constexpr bool is_method = false;
tzikc1db72652016-07-08 09:42:38418 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12419
420 template <typename... RunArgs>
421 static R Invoke(R(__stdcall* function)(Args...), RunArgs&&... args) {
422 return function(std::forward<RunArgs>(args)...);
423 }
424};
425
426// For functions.
427template <typename R, typename... Args>
428struct FunctorTraits<R(__fastcall*)(Args...)> {
429 using RunType = R(Args...);
430 static constexpr bool is_method = false;
tzikc1db72652016-07-08 09:42:38431 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12432
433 template <typename... RunArgs>
434 static R Invoke(R(__fastcall* function)(Args...), RunArgs&&... args) {
435 return function(std::forward<RunArgs>(args)...);
436 }
437};
438
439#endif // defined(OS_WIN) && !defined(ARCH_CPU_X86_64)
440
Sylvain Defresneec3270c2018-05-31 17:19:15441#if defined(OS_MACOSX)
442
443// Support for Objective-C blocks. There are two implementation depending
444// on whether Automated Reference Counting (ARC) is enabled. When ARC is
445// enabled, then the block itself can be bound as the compiler will ensure
446// its lifetime will be correctly managed. Otherwise, require the block to
447// be wrapped in a base::mac::ScopedBlock (via base::RetainBlock) that will
448// correctly manage the block lifetime.
449//
450// The two implementation ensure that the One Definition Rule (ODR) is not
451// broken (it is not possible to write a template base::RetainBlock that would
452// work correctly both with ARC enabled and disabled).
453
454#if HAS_FEATURE(objc_arc)
455
456template <typename R, typename... Args>
457struct FunctorTraits<R (^)(Args...)> {
458 using RunType = R(Args...);
459 static constexpr bool is_method = false;
460 static constexpr bool is_nullable = true;
461
462 template <typename BlockType, typename... RunArgs>
463 static R Invoke(BlockType&& block, RunArgs&&... args) {
464 // According to LLVM documentation (§ 6.3), "local variables of automatic
465 // storage duration do not have precise lifetime." Use objc_precise_lifetime
466 // to ensure that the Objective-C block is not deallocated until it has
467 // finished executing even if the Callback<> is destroyed during the block
468 // execution.
469 // https://clang.llvm.org/docs/AutomaticReferenceCounting.html#precise-lifetime-semantics
470 __attribute__((objc_precise_lifetime)) R (^scoped_block)(Args...) = block;
471 return scoped_block(std::forward<RunArgs>(args)...);
472 }
473};
474
475#else // HAS_FEATURE(objc_arc)
476
477template <typename R, typename... Args>
478struct FunctorTraits<base::mac::ScopedBlock<R (^)(Args...)>> {
479 using RunType = R(Args...);
480 static constexpr bool is_method = false;
481 static constexpr bool is_nullable = true;
482
483 template <typename BlockType, typename... RunArgs>
484 static R Invoke(BlockType&& block, RunArgs&&... args) {
485 // Copy the block to ensure that the Objective-C block is not deallocated
486 // until it has finished executing even if the Callback<> is destroyed
487 // during the block execution.
488 base::mac::ScopedBlock<R (^)(Args...)> scoped_block(block);
489 return scoped_block.get()(std::forward<RunArgs>(args)...);
490 }
491};
492
493#endif // HAS_FEATURE(objc_arc)
494#endif // defined(OS_MACOSX)
495
tzik99de02b2016-07-01 05:54:12496// For methods.
497template <typename R, typename Receiver, typename... Args>
498struct FunctorTraits<R (Receiver::*)(Args...)> {
499 using RunType = R(Receiver*, Args...);
500 static constexpr bool is_method = true;
tzikc1db72652016-07-08 09:42:38501 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12502
tzikd58a89232018-04-26 04:29:53503 template <typename Method, typename ReceiverPtr, typename... RunArgs>
504 static R Invoke(Method method,
tzik99de02b2016-07-01 05:54:12505 ReceiverPtr&& receiver_ptr,
506 RunArgs&&... args) {
tzik75851f42017-06-14 06:57:01507 return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
tzik99de02b2016-07-01 05:54:12508 }
509};
510
511// For const methods.
512template <typename R, typename Receiver, typename... Args>
513struct FunctorTraits<R (Receiver::*)(Args...) const> {
514 using RunType = R(const Receiver*, Args...);
515 static constexpr bool is_method = true;
tzikc1db72652016-07-08 09:42:38516 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12517
tzikd58a89232018-04-26 04:29:53518 template <typename Method, typename ReceiverPtr, typename... RunArgs>
519 static R Invoke(Method method,
tzik99de02b2016-07-01 05:54:12520 ReceiverPtr&& receiver_ptr,
521 RunArgs&&... args) {
tzik75851f42017-06-14 06:57:01522 return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
tzik99de02b2016-07-01 05:54:12523 }
524};
525
tzikd58a89232018-04-26 04:29:53526#ifdef __cpp_noexcept_function_type
527// noexcept makes a distinct function type in C++17.
528// I.e. `void(*)()` and `void(*)() noexcept` are same in pre-C++17, and
529// different in C++17.
530template <typename R, typename... Args>
531struct FunctorTraits<R (*)(Args...) noexcept> : FunctorTraits<R (*)(Args...)> {
532};
533
534template <typename R, typename Receiver, typename... Args>
535struct FunctorTraits<R (Receiver::*)(Args...) noexcept>
536 : FunctorTraits<R (Receiver::*)(Args...)> {};
537
538template <typename R, typename Receiver, typename... Args>
539struct FunctorTraits<R (Receiver::*)(Args...) const noexcept>
540 : FunctorTraits<R (Receiver::*)(Args...) const> {};
541#endif
542
tzik99de02b2016-07-01 05:54:12543// For IgnoreResults.
[email protected]7296f2762011-11-21 19:23:44544template <typename T>
tzik99de02b2016-07-01 05:54:12545struct FunctorTraits<IgnoreResultHelper<T>> : FunctorTraits<T> {
tzik3bc7779b2015-12-19 09:18:46546 using RunType =
tzik99de02b2016-07-01 05:54:12547 typename ForceVoidReturn<typename FunctorTraits<T>::RunType>::RunType;
548
549 template <typename IgnoreResultType, typename... RunArgs>
550 static void Invoke(IgnoreResultType&& ignore_result_helper,
551 RunArgs&&... args) {
tzikff54a5b152016-08-31 11:50:41552 FunctorTraits<T>::Invoke(
553 std::forward<IgnoreResultType>(ignore_result_helper).functor_,
554 std::forward<RunArgs>(args)...);
tzik99de02b2016-07-01 05:54:12555 }
[email protected]7296f2762011-11-21 19:23:44556};
557
tzikd4bb5b7d2017-08-28 19:08:52558// For OnceCallbacks.
559template <typename R, typename... Args>
560struct FunctorTraits<OnceCallback<R(Args...)>> {
561 using RunType = R(Args...);
562 static constexpr bool is_method = false;
563 static constexpr bool is_nullable = true;
564
565 template <typename CallbackType, typename... RunArgs>
566 static R Invoke(CallbackType&& callback, RunArgs&&... args) {
567 DCHECK(!callback.is_null());
568 return std::forward<CallbackType>(callback).Run(
569 std::forward<RunArgs>(args)...);
570 }
571};
572
573// For RepeatingCallbacks.
574template <typename R, typename... Args>
575struct FunctorTraits<RepeatingCallback<R(Args...)>> {
tzik99de02b2016-07-01 05:54:12576 using RunType = R(Args...);
577 static constexpr bool is_method = false;
tzikc1db72652016-07-08 09:42:38578 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12579
580 template <typename CallbackType, typename... RunArgs>
581 static R Invoke(CallbackType&& callback, RunArgs&&... args) {
582 DCHECK(!callback.is_null());
583 return std::forward<CallbackType>(callback).Run(
584 std::forward<RunArgs>(args)...);
585 }
[email protected]7296f2762011-11-21 19:23:44586};
587
tzikae4202e2017-07-31 10:41:54588template <typename Functor>
Jeremy Roman35a317432017-08-16 22:20:53589using MakeFunctorTraits = FunctorTraits<std::decay_t<Functor>>;
tzikae4202e2017-07-31 10:41:54590
[email protected]7296f2762011-11-21 19:23:44591// InvokeHelper<>
592//
tzik99de02b2016-07-01 05:54:12593// There are 2 logical InvokeHelper<> specializations: normal, WeakCalls.
[email protected]7296f2762011-11-21 19:23:44594//
595// The normal type just calls the underlying runnable.
596//
tzik99de02b2016-07-01 05:54:12597// WeakCalls need special syntax that is applied to the first argument to check
598// if they should no-op themselves.
tzikee248722016-06-01 08:22:51599template <bool is_weak_call, typename ReturnType>
[email protected]7296f2762011-11-21 19:23:44600struct InvokeHelper;
601
tzikee248722016-06-01 08:22:51602template <typename ReturnType>
603struct InvokeHelper<false, ReturnType> {
tzik99de02b2016-07-01 05:54:12604 template <typename Functor, typename... RunArgs>
605 static inline ReturnType MakeItSo(Functor&& functor, RunArgs&&... args) {
tzikae4202e2017-07-31 10:41:54606 using Traits = MakeFunctorTraits<Functor>;
tzik99de02b2016-07-01 05:54:12607 return Traits::Invoke(std::forward<Functor>(functor),
608 std::forward<RunArgs>(args)...);
[email protected]7296f2762011-11-21 19:23:44609 }
610};
611
tzikee248722016-06-01 08:22:51612template <typename ReturnType>
613struct InvokeHelper<true, ReturnType> {
[email protected]7296f2762011-11-21 19:23:44614 // WeakCalls are only supported for functions with a void return type.
615 // Otherwise, the function result would be undefined if the the WeakPtr<>
616 // is invalidated.
tzik403cb6c2016-03-10 07:17:25617 static_assert(std::is_void<ReturnType>::value,
avi4ec0dff2015-11-24 14:26:24618 "weak_ptrs can only bind to methods without return values");
[email protected]c18b1052011-03-24 02:02:17619
tzik99de02b2016-07-01 05:54:12620 template <typename Functor, typename BoundWeakPtr, typename... RunArgs>
621 static inline void MakeItSo(Functor&& functor,
tzik33871d82016-07-14 12:12:06622 BoundWeakPtr&& weak_ptr,
tzik99de02b2016-07-01 05:54:12623 RunArgs&&... args) {
624 if (!weak_ptr)
625 return;
tzikae4202e2017-07-31 10:41:54626 using Traits = MakeFunctorTraits<Functor>;
tzik99de02b2016-07-01 05:54:12627 Traits::Invoke(std::forward<Functor>(functor),
628 std::forward<BoundWeakPtr>(weak_ptr),
629 std::forward<RunArgs>(args)...);
630 }
631};
[email protected]b38d3572011-02-15 01:27:38632
[email protected]7296f2762011-11-21 19:23:44633// Invoker<>
634//
635// See description at the top of the file.
tzikcaf1d84b2016-06-28 12:22:21636template <typename StorageType, typename UnboundRunType>
[email protected]7296f2762011-11-21 19:23:44637struct Invoker;
638
tzikcaf1d84b2016-06-28 12:22:21639template <typename StorageType, typename R, typename... UnboundArgs>
640struct Invoker<StorageType, R(UnboundArgs...)> {
Vladislav Kuzkokov6d208e12017-11-08 21:31:08641 static R RunOnce(BindStateBase* base,
642 PassingTraitsType<UnboundArgs>... unbound_args) {
tzik27d1e312016-09-13 05:28:59643 // Local references to make debugger stepping easier. If in a debugger,
644 // you really want to warp ahead and step through the
645 // InvokeHelper<>::MakeItSo() call below.
646 StorageType* storage = static_cast<StorageType*>(base);
647 static constexpr size_t num_bound_args =
648 std::tuple_size<decltype(storage->bound_args_)>::value;
649 return RunImpl(std::move(storage->functor_),
650 std::move(storage->bound_args_),
Jeremy Roman84956fa2017-08-16 15:55:20651 std::make_index_sequence<num_bound_args>(),
tzik27d1e312016-09-13 05:28:59652 std::forward<UnboundArgs>(unbound_args)...);
653 }
654
Vladislav Kuzkokov6d208e12017-11-08 21:31:08655 static R Run(BindStateBase* base,
656 PassingTraitsType<UnboundArgs>... unbound_args) {
[email protected]7296f2762011-11-21 19:23:44657 // Local references to make debugger stepping easier. If in a debugger,
658 // you really want to warp ahead and step through the
659 // InvokeHelper<>::MakeItSo() call below.
tzikcaf1d84b2016-06-28 12:22:21660 const StorageType* storage = static_cast<StorageType*>(base);
661 static constexpr size_t num_bound_args =
662 std::tuple_size<decltype(storage->bound_args_)>::value;
Jeremy Roman84956fa2017-08-16 15:55:20663 return RunImpl(storage->functor_, storage->bound_args_,
664 std::make_index_sequence<num_bound_args>(),
tzikcaf1d84b2016-06-28 12:22:21665 std::forward<UnboundArgs>(unbound_args)...);
666 }
667
tzik99de02b2016-07-01 05:54:12668 private:
669 template <typename Functor, typename BoundArgsTuple, size_t... indices>
670 static inline R RunImpl(Functor&& functor,
tzikcaf1d84b2016-06-28 12:22:21671 BoundArgsTuple&& bound,
Jeremy Roman84956fa2017-08-16 15:55:20672 std::index_sequence<indices...>,
tzikcaf1d84b2016-06-28 12:22:21673 UnboundArgs&&... unbound_args) {
tzikae4202e2017-07-31 10:41:54674 static constexpr bool is_method = MakeFunctorTraits<Functor>::is_method;
tzikcaf1d84b2016-06-28 12:22:21675
Jeremy Roman35a317432017-08-16 22:20:53676 using DecayedArgsTuple = std::decay_t<BoundArgsTuple>;
tzikcaf1d84b2016-06-28 12:22:21677 static constexpr bool is_weak_call =
678 IsWeakMethod<is_method,
Jeremy Roman35a317432017-08-16 22:20:53679 std::tuple_element_t<indices, DecayedArgsTuple>...>();
tzikcaf1d84b2016-06-28 12:22:21680
tzikee248722016-06-01 08:22:51681 return InvokeHelper<is_weak_call, R>::MakeItSo(
tzik99de02b2016-07-01 05:54:12682 std::forward<Functor>(functor),
tzikf7c47572017-04-05 21:45:03683 Unwrap(std::get<indices>(std::forward<BoundArgsTuple>(bound)))...,
tzika43eff02016-03-09 05:46:05684 std::forward<UnboundArgs>(unbound_args)...);
[email protected]fccef1552011-11-28 22:13:54685 }
686};
687
tzikae4202e2017-07-31 10:41:54688// Extracts necessary type info from Functor and BoundArgs.
689// Used to implement MakeUnboundRunType, BindOnce and BindRepeating.
tzikcaf1d84b2016-06-28 12:22:21690template <typename Functor, typename... BoundArgs>
tzikae4202e2017-07-31 10:41:54691struct BindTypeHelper {
692 static constexpr size_t num_bounds = sizeof...(BoundArgs);
693 using FunctorTraits = MakeFunctorTraits<Functor>;
694
695 // Example:
696 // When Functor is `double (Foo::*)(int, const std::string&)`, and BoundArgs
697 // is a template pack of `Foo*` and `int16_t`:
698 // - RunType is `double(Foo*, int, const std::string&)`,
699 // - ReturnType is `double`,
700 // - RunParamsList is `TypeList<Foo*, int, const std::string&>`,
701 // - BoundParamsList is `TypeList<Foo*, int>`,
702 // - UnboundParamsList is `TypeList<const std::string&>`,
703 // - BoundArgsList is `TypeList<Foo*, int16_t>`,
704 // - UnboundRunType is `double(const std::string&)`.
705 using RunType = typename FunctorTraits::RunType;
tzikcaf1d84b2016-06-28 12:22:21706 using ReturnType = ExtractReturnType<RunType>;
tzikae4202e2017-07-31 10:41:54707
708 using RunParamsList = ExtractArgs<RunType>;
709 using BoundParamsList = TakeTypeListItem<num_bounds, RunParamsList>;
710 using UnboundParamsList = DropTypeListItem<num_bounds, RunParamsList>;
711
712 using BoundArgsList = TypeList<BoundArgs...>;
713
714 using UnboundRunType = MakeFunctionType<ReturnType, UnboundParamsList>;
tzikcaf1d84b2016-06-28 12:22:21715};
tzikae4202e2017-07-31 10:41:54716
tzikc1db72652016-07-08 09:42:38717template <typename Functor>
Jeremy Roman35a317432017-08-16 22:20:53718std::enable_if_t<FunctorTraits<Functor>::is_nullable, bool> IsNull(
719 const Functor& functor) {
tzikc1db72652016-07-08 09:42:38720 return !functor;
721}
722
723template <typename Functor>
Jeremy Roman35a317432017-08-16 22:20:53724std::enable_if_t<!FunctorTraits<Functor>::is_nullable, bool> IsNull(
725 const Functor&) {
tzikc1db72652016-07-08 09:42:38726 return false;
727}
tzikcaf1d84b2016-06-28 12:22:21728
tzik6c92eab2016-11-25 15:56:36729// Used by ApplyCancellationTraits below.
730template <typename Functor, typename BoundArgsTuple, size_t... indices>
731bool ApplyCancellationTraitsImpl(const Functor& functor,
732 const BoundArgsTuple& bound_args,
Jeremy Roman84956fa2017-08-16 15:55:20733 std::index_sequence<indices...>) {
tzik6c92eab2016-11-25 15:56:36734 return CallbackCancellationTraits<Functor, BoundArgsTuple>::IsCancelled(
tzikf7c47572017-04-05 21:45:03735 functor, std::get<indices>(bound_args)...);
tzik6c92eab2016-11-25 15:56:36736}
tzik59aa6bb12016-09-08 10:58:53737
tzik6c92eab2016-11-25 15:56:36738// Relays |base| to corresponding CallbackCancellationTraits<>::Run(). Returns
739// true if the callback |base| represents is canceled.
740template <typename BindStateType>
741bool ApplyCancellationTraits(const BindStateBase* base) {
742 const BindStateType* storage = static_cast<const BindStateType*>(base);
743 static constexpr size_t num_bound_args =
744 std::tuple_size<decltype(storage->bound_args_)>::value;
Jeremy Roman84956fa2017-08-16 15:55:20745 return ApplyCancellationTraitsImpl(
746 storage->functor_, storage->bound_args_,
747 std::make_index_sequence<num_bound_args>());
tzik59aa6bb12016-09-08 10:58:53748};
749
[email protected]7296f2762011-11-21 19:23:44750// BindState<>
751//
tzik99de02b2016-07-01 05:54:12752// This stores all the state passed into Bind().
753template <typename Functor, typename... BoundArgs>
754struct BindState final : BindStateBase {
tzik1fdcca32016-09-14 07:15:00755 using IsCancellable = std::integral_constant<
tzik6c92eab2016-11-25 15:56:36756 bool,
757 CallbackCancellationTraits<Functor,
758 std::tuple<BoundArgs...>>::is_cancellable>;
tzik1fdcca32016-09-14 07:15:00759
tzikbfe66122016-07-08 14:14:01760 template <typename ForwardFunctor, typename... ForwardBoundArgs>
tzik1886c272016-09-08 05:45:38761 explicit BindState(BindStateBase::InvokeFuncStorage invoke_func,
762 ForwardFunctor&& functor,
763 ForwardBoundArgs&&... bound_args)
tzik6c92eab2016-11-25 15:56:36764 // IsCancellable is std::false_type if
765 // CallbackCancellationTraits<>::IsCancelled returns always false.
766 // Otherwise, it's std::true_type.
tzik1fdcca32016-09-14 07:15:00767 : BindState(IsCancellable{},
768 invoke_func,
769 std::forward<ForwardFunctor>(functor),
tzikf98654b2017-12-02 03:28:58770 std::forward<ForwardBoundArgs>(bound_args)...) {}
tzik1fdcca32016-09-14 07:15:00771
772 Functor functor_;
773 std::tuple<BoundArgs...> bound_args_;
774
775 private:
776 template <typename ForwardFunctor, typename... ForwardBoundArgs>
777 explicit BindState(std::true_type,
778 BindStateBase::InvokeFuncStorage invoke_func,
779 ForwardFunctor&& functor,
780 ForwardBoundArgs&&... bound_args)
tzik6c92eab2016-11-25 15:56:36781 : BindStateBase(invoke_func,
782 &Destroy,
783 &ApplyCancellationTraits<BindState>),
tzikff54a5b152016-08-31 11:50:41784 functor_(std::forward<ForwardFunctor>(functor)),
tzik99de02b2016-07-01 05:54:12785 bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
tzikc1db72652016-07-08 09:42:38786 DCHECK(!IsNull(functor_));
tzik99de02b2016-07-01 05:54:12787 }
[email protected]7296f2762011-11-21 19:23:44788
tzik1fdcca32016-09-14 07:15:00789 template <typename ForwardFunctor, typename... ForwardBoundArgs>
790 explicit BindState(std::false_type,
791 BindStateBase::InvokeFuncStorage invoke_func,
792 ForwardFunctor&& functor,
793 ForwardBoundArgs&&... bound_args)
794 : BindStateBase(invoke_func, &Destroy),
795 functor_(std::forward<ForwardFunctor>(functor)),
796 bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
797 DCHECK(!IsNull(functor_));
798 }
dmichael7d09007e2014-12-18 22:30:11799
Chris Watkins091d6292017-12-13 04:25:58800 ~BindState() = default;
taptede7e804c2015-05-14 08:03:32801
tzik30e0c312016-09-21 08:06:54802 static void Destroy(const BindStateBase* self) {
803 delete static_cast<const BindState*>(self);
taptede7e804c2015-05-14 08:03:32804 }
[email protected]fccef1552011-11-28 22:13:54805};
806
tzik99de02b2016-07-01 05:54:12807// Used to implement MakeBindStateType.
808template <bool is_method, typename Functor, typename... BoundArgs>
809struct MakeBindStateTypeImpl;
810
811template <typename Functor, typename... BoundArgs>
812struct MakeBindStateTypeImpl<false, Functor, BoundArgs...> {
Jeremy Roman35a317432017-08-16 22:20:53813 static_assert(!HasRefCountedTypeAsRawPtr<std::decay_t<BoundArgs>...>::value,
tzik99de02b2016-07-01 05:54:12814 "A parameter is a refcounted type and needs scoped_refptr.");
Jeremy Roman35a317432017-08-16 22:20:53815 using Type = BindState<std::decay_t<Functor>, std::decay_t<BoundArgs>...>;
tzik99de02b2016-07-01 05:54:12816};
817
818template <typename Functor>
819struct MakeBindStateTypeImpl<true, Functor> {
Jeremy Roman35a317432017-08-16 22:20:53820 using Type = BindState<std::decay_t<Functor>>;
tzik99de02b2016-07-01 05:54:12821};
822
823template <typename Functor, typename Receiver, typename... BoundArgs>
824struct MakeBindStateTypeImpl<true, Functor, Receiver, BoundArgs...> {
tzik99de02b2016-07-01 05:54:12825 private:
Jeremy Roman35a317432017-08-16 22:20:53826 using DecayedReceiver = std::decay_t<Receiver>;
tzik99de02b2016-07-01 05:54:12827
tzik4625ac612018-02-28 09:43:55828 static_assert(!std::is_array<std::remove_reference_t<Receiver>>::value,
829 "First bound argument to a method cannot be an array.");
830 static_assert(
831 !std::is_pointer<DecayedReceiver>::value ||
832 IsRefCountedType<std::remove_pointer_t<DecayedReceiver>>::value,
833 "Receivers may not be raw pointers. If using a raw pointer here is safe"
834 " and has no lifetime concerns, use base::Unretained() and document why"
835 " it's safe.");
836 static_assert(!HasRefCountedTypeAsRawPtr<std::decay_t<BoundArgs>...>::value,
837 "A parameter is a refcounted type and needs scoped_refptr.");
838
tzik99de02b2016-07-01 05:54:12839 public:
840 using Type = BindState<
Jeremy Roman35a317432017-08-16 22:20:53841 std::decay_t<Functor>,
842 std::conditional_t<std::is_pointer<DecayedReceiver>::value,
843 scoped_refptr<std::remove_pointer_t<DecayedReceiver>>,
844 DecayedReceiver>,
845 std::decay_t<BoundArgs>...>;
tzik99de02b2016-07-01 05:54:12846};
847
848template <typename Functor, typename... BoundArgs>
tzikae4202e2017-07-31 10:41:54849using MakeBindStateType =
850 typename MakeBindStateTypeImpl<MakeFunctorTraits<Functor>::is_method,
851 Functor,
852 BoundArgs...>::Type;
tzik99de02b2016-07-01 05:54:12853
[email protected]b38d3572011-02-15 01:27:38854} // namespace internal
tzikcaf1d84b2016-06-28 12:22:21855
Peter Kastinga85265e32018-02-15 08:30:23856// An injection point to control |this| pointer behavior on a method invocation.
857// If IsWeakReceiver<> is true_type for |T| and |T| is used for a receiver of a
858// method, base::Bind cancels the method invocation if the receiver is tested as
859// false.
860// E.g. Foo::bar() is not called:
861// struct Foo : base::SupportsWeakPtr<Foo> {
862// void bar() {}
863// };
864//
865// WeakPtr<Foo> oo = nullptr;
866// base::Bind(&Foo::bar, oo).Run();
867template <typename T>
868struct IsWeakReceiver : std::false_type {};
869
870template <typename T>
871struct IsWeakReceiver<internal::ConstRefWrapper<T>> : IsWeakReceiver<T> {};
872
873template <typename T>
874struct IsWeakReceiver<WeakPtr<T>> : std::true_type {};
875
876// An injection point to control how bound objects passed to the target
877// function. BindUnwrapTraits<>::Unwrap() is called for each bound objects right
878// before the target function is invoked.
879template <typename>
880struct BindUnwrapTraits {
881 template <typename T>
882 static T&& Unwrap(T&& o) {
883 return std::forward<T>(o);
884 }
885};
886
887template <typename T>
888struct BindUnwrapTraits<internal::UnretainedWrapper<T>> {
889 static T* Unwrap(const internal::UnretainedWrapper<T>& o) { return o.get(); }
890};
891
892template <typename T>
893struct BindUnwrapTraits<internal::ConstRefWrapper<T>> {
894 static const T& Unwrap(const internal::ConstRefWrapper<T>& o) {
895 return o.get();
896 }
897};
898
899template <typename T>
900struct BindUnwrapTraits<internal::RetainedRefWrapper<T>> {
901 static T* Unwrap(const internal::RetainedRefWrapper<T>& o) { return o.get(); }
902};
903
904template <typename T>
905struct BindUnwrapTraits<internal::OwnedWrapper<T>> {
906 static T* Unwrap(const internal::OwnedWrapper<T>& o) { return o.get(); }
907};
908
909template <typename T>
910struct BindUnwrapTraits<internal::PassedWrapper<T>> {
911 static T Unwrap(const internal::PassedWrapper<T>& o) { return o.Take(); }
912};
913
914// CallbackCancellationTraits allows customization of Callback's cancellation
915// semantics. By default, callbacks are not cancellable. A specialization should
916// set is_cancellable = true and implement an IsCancelled() that returns if the
917// callback should be cancelled.
918template <typename Functor, typename BoundArgsTuple, typename SFINAE>
919struct CallbackCancellationTraits {
920 static constexpr bool is_cancellable = false;
921};
922
923// Specialization for method bound to weak pointer receiver.
924template <typename Functor, typename... BoundArgs>
925struct CallbackCancellationTraits<
926 Functor,
927 std::tuple<BoundArgs...>,
928 std::enable_if_t<
929 internal::IsWeakMethod<internal::FunctorTraits<Functor>::is_method,
930 BoundArgs...>::value>> {
931 static constexpr bool is_cancellable = true;
932
933 template <typename Receiver, typename... Args>
934 static bool IsCancelled(const Functor&,
935 const Receiver& receiver,
936 const Args&...) {
937 return !receiver;
938 }
939};
940
941// Specialization for a nested bind.
942template <typename Signature, typename... BoundArgs>
943struct CallbackCancellationTraits<OnceCallback<Signature>,
944 std::tuple<BoundArgs...>> {
945 static constexpr bool is_cancellable = true;
946
947 template <typename Functor>
948 static bool IsCancelled(const Functor& functor, const BoundArgs&...) {
949 return functor.IsCancelled();
950 }
951};
952
953template <typename Signature, typename... BoundArgs>
954struct CallbackCancellationTraits<RepeatingCallback<Signature>,
955 std::tuple<BoundArgs...>> {
956 static constexpr bool is_cancellable = true;
957
958 template <typename Functor>
959 static bool IsCancelled(const Functor& functor, const BoundArgs&...) {
960 return functor.IsCancelled();
961 }
962};
963
tzikcaf1d84b2016-06-28 12:22:21964// Returns a RunType of bound functor.
965// E.g. MakeUnboundRunType<R(A, B, C), A, B> is evaluated to R(C).
966template <typename Functor, typename... BoundArgs>
967using MakeUnboundRunType =
tzikae4202e2017-07-31 10:41:54968 typename internal::BindTypeHelper<Functor, BoundArgs...>::UnboundRunType;
tzikcaf1d84b2016-06-28 12:22:21969
[email protected]b38d3572011-02-15 01:27:38970} // namespace base
971
972#endif // BASE_BIND_INTERNAL_H_