blob: c69d138ac9759cd687d70adc10adfcf679f7b003 [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
jdoerriec79c2fa22019-02-26 12:35:0310#include <functional>
jdoerrie68f2d51b2019-02-28 17:32:4411#include <memory>
jdoerrie5c4dc4e2019-02-01 18:02:3312#include <tuple>
vmpstrc52317f2015-11-18 08:43:2613#include <type_traits>
Jeremy Roman84956fa2017-08-16 15:55:2014#include <utility>
vmpstrc52317f2015-11-18 08:43:2615
Sebastien Marchand6d0558fd2019-01-25 16:49:3716#include "base/bind.h"
[email protected]59eff912011-02-18 23:29:3117#include "base/callback_internal.h"
Hans Wennborg7b533712020-06-22 20:52:2718#include "base/check.h"
Sylvain Defresneec3270c2018-05-31 17:19:1519#include "base/compiler_specific.h"
[email protected]8217d4542011-10-01 06:31:4120#include "base/memory/raw_scoped_refptr_mismatch_checker.h"
[email protected]93540582011-05-16 22:35:1421#include "base/memory/weak_ptr.h"
Hans Wennborg7b533712020-06-22 20:52:2722#include "base/notreached.h"
[email protected]b38d3572011-02-15 01:27:3823#include "base/template_util.h"
[email protected]054ac7542011-02-27 01:25:5924#include "build/build_config.h"
25
Avi Drissman5b286372020-07-28 21:59:3826#if defined(OS_APPLE) && !HAS_FEATURE(objc_arc)
Sylvain Defresneec3270c2018-05-31 17:19:1527#include "base/mac/scoped_block.h"
28#endif
29
[email protected]24292642012-07-12 20:06:4030// See base/callback.h for user documentation.
31//
32//
[email protected]7296f2762011-11-21 19:23:4433// CONCEPTS:
tzik99de02b2016-07-01 05:54:1234// Functor -- A movable type representing something that should be called.
35// All function pointers and Callback<> are functors even if the
36// invocation syntax differs.
[email protected]7296f2762011-11-21 19:23:4437// RunType -- A function type (as opposed to function _pointer_ type) for
tzik99de02b2016-07-01 05:54:1238// a Callback<>::Run(). Usually just a convenience typedef.
tzikce3ecf82015-12-15 06:41:4939// (Bound)Args -- A set of types that stores the arguments.
[email protected]b38d3572011-02-15 01:27:3840//
[email protected]7296f2762011-11-21 19:23:4441// Types:
[email protected]7296f2762011-11-21 19:23:4442// ForceVoidReturn<> -- Helper class for translating function signatures to
43// equivalent forms with a "void" return type.
tzik99de02b2016-07-01 05:54:1244// FunctorTraits<> -- Type traits used to determine the correct RunType and
45// invocation manner for a Functor. This is where function
[email protected]7296f2762011-11-21 19:23:4446// signature adapters are applied.
tzik99de02b2016-07-01 05:54:1247// InvokeHelper<> -- Take a Functor + arguments and actully invokes it.
tzik8ce65702015-02-05 19:11:2648// Handle the differing syntaxes needed for WeakPtr<>
tzik99de02b2016-07-01 05:54:1249// support. This is separate from Invoker to avoid creating
50// multiple version of Invoker<>.
51// Invoker<> -- Unwraps the curried parameters and executes the Functor.
[email protected]7296f2762011-11-21 19:23:4452// BindState<> -- Stores the curried parameters, and is the main entry point
tzik99de02b2016-07-01 05:54:1253// into the Bind() system.
[email protected]4346ef912011-02-19 00:52:1554
tzikc44f8102018-07-24 09:49:1955#if defined(OS_WIN)
56namespace Microsoft {
57namespace WRL {
58template <typename>
59class ComPtr;
60} // namespace WRL
61} // namespace Microsoft
62#endif
63
Peter Kastinga85265e32018-02-15 08:30:2364namespace base {
65
66template <typename T>
67struct IsWeakReceiver;
68
69template <typename>
70struct BindUnwrapTraits;
71
72template <typename Functor, typename BoundArgsTuple, typename SFINAE = void>
73struct CallbackCancellationTraits;
74
75namespace internal {
76
77template <typename Functor, typename SFINAE = void>
78struct FunctorTraits;
79
80template <typename T>
81class UnretainedWrapper {
82 public:
83 explicit UnretainedWrapper(T* o) : ptr_(o) {}
84 T* get() const { return ptr_; }
85
86 private:
87 T* ptr_;
88};
89
90template <typename T>
Peter Kastinga85265e32018-02-15 08:30:2391class RetainedRefWrapper {
92 public:
93 explicit RetainedRefWrapper(T* o) : ptr_(o) {}
94 explicit RetainedRefWrapper(scoped_refptr<T> o) : ptr_(std::move(o)) {}
95 T* get() const { return ptr_.get(); }
96
97 private:
98 scoped_refptr<T> ptr_;
99};
100
101template <typename T>
102struct IgnoreResultHelper {
103 explicit IgnoreResultHelper(T functor) : functor_(std::move(functor)) {}
104 explicit operator bool() const { return !!functor_; }
105
106 T functor_;
107};
108
Marijn Kruisselbrinkc1e775f2019-12-19 01:24:22109template <typename T, typename Deleter = std::default_delete<T>>
Peter Kastinga85265e32018-02-15 08:30:23110class OwnedWrapper {
111 public:
112 explicit OwnedWrapper(T* o) : ptr_(o) {}
Marijn Kruisselbrinkc1e775f2019-12-19 01:24:22113 explicit OwnedWrapper(std::unique_ptr<T, Deleter>&& ptr)
114 : ptr_(std::move(ptr)) {}
jdoerrie68f2d51b2019-02-28 17:32:44115 T* get() const { return ptr_.get(); }
Peter Kastinga85265e32018-02-15 08:30:23116
117 private:
Marijn Kruisselbrinkc1e775f2019-12-19 01:24:22118 std::unique_ptr<T, Deleter> ptr_;
Peter Kastinga85265e32018-02-15 08:30:23119};
120
121// PassedWrapper is a copyable adapter for a scoper that ignores const.
122//
123// It is needed to get around the fact that Bind() takes a const reference to
124// all its arguments. Because Bind() takes a const reference to avoid
125// unnecessary copies, it is incompatible with movable-but-not-copyable
126// types; doing a destructive "move" of the type into Bind() would violate
127// the const correctness.
128//
129// This conundrum cannot be solved without either C++11 rvalue references or
130// a O(2^n) blowup of Bind() templates to handle each combination of regular
131// types and movable-but-not-copyable types. Thus we introduce a wrapper type
132// that is copyable to transmit the correct type information down into
133// BindState<>. Ignoring const in this type makes sense because it is only
134// created when we are explicitly trying to do a destructive move.
135//
136// Two notes:
137// 1) PassedWrapper supports any type that has a move constructor, however
138// the type will need to be specifically whitelisted in order for it to be
139// bound to a Callback. We guard this explicitly at the call of Passed()
140// to make for clear errors. Things not given to Passed() will be forwarded
141// and stored by value which will not work for general move-only types.
142// 2) is_valid_ is distinct from NULL because it is valid to bind a "NULL"
143// scoper to a Callback and allow the Callback to execute once.
144template <typename T>
145class PassedWrapper {
146 public:
147 explicit PassedWrapper(T&& scoper)
148 : is_valid_(true), scoper_(std::move(scoper)) {}
149 PassedWrapper(PassedWrapper&& other)
150 : is_valid_(other.is_valid_), scoper_(std::move(other.scoper_)) {}
151 T Take() const {
152 CHECK(is_valid_);
153 is_valid_ = false;
154 return std::move(scoper_);
155 }
156
157 private:
158 mutable bool is_valid_;
159 mutable T scoper_;
160};
161
162template <typename T>
163using Unwrapper = BindUnwrapTraits<std::decay_t<T>>;
164
165template <typename T>
Peter Kastingc2f8749bf2018-03-31 03:32:37166decltype(auto) Unwrap(T&& o) {
Peter Kastinga85265e32018-02-15 08:30:23167 return Unwrapper<T>::Unwrap(std::forward<T>(o));
168}
169
170// IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a
171// method. It is used internally by Bind() to select the correct
172// InvokeHelper that will no-op itself in the event the WeakPtr<> for
173// the target object is invalidated.
174//
175// The first argument should be the type of the object that will be received by
176// the method.
177template <bool is_method, typename... Args>
178struct IsWeakMethod : std::false_type {};
179
180template <typename T, typename... Args>
181struct IsWeakMethod<true, T, Args...> : IsWeakReceiver<T> {};
182
183// Packs a list of types to hold them in a single type.
184template <typename... Types>
185struct TypeList {};
186
187// Used for DropTypeListItem implementation.
188template <size_t n, typename List>
189struct DropTypeListItemImpl;
190
191// Do not use enable_if and SFINAE here to avoid MSVC2013 compile failure.
192template <size_t n, typename T, typename... List>
193struct DropTypeListItemImpl<n, TypeList<T, List...>>
194 : DropTypeListItemImpl<n - 1, TypeList<List...>> {};
195
196template <typename T, typename... List>
197struct DropTypeListItemImpl<0, TypeList<T, List...>> {
198 using Type = TypeList<T, List...>;
199};
200
201template <>
202struct DropTypeListItemImpl<0, TypeList<>> {
203 using Type = TypeList<>;
204};
205
206// A type-level function that drops |n| list item from given TypeList.
207template <size_t n, typename List>
208using DropTypeListItem = typename DropTypeListItemImpl<n, List>::Type;
209
210// Used for TakeTypeListItem implementation.
211template <size_t n, typename List, typename... Accum>
212struct TakeTypeListItemImpl;
213
214// Do not use enable_if and SFINAE here to avoid MSVC2013 compile failure.
215template <size_t n, typename T, typename... List, typename... Accum>
216struct TakeTypeListItemImpl<n, TypeList<T, List...>, Accum...>
217 : TakeTypeListItemImpl<n - 1, TypeList<List...>, Accum..., T> {};
218
219template <typename T, typename... List, typename... Accum>
220struct TakeTypeListItemImpl<0, TypeList<T, List...>, Accum...> {
221 using Type = TypeList<Accum...>;
222};
223
224template <typename... Accum>
225struct TakeTypeListItemImpl<0, TypeList<>, Accum...> {
226 using Type = TypeList<Accum...>;
227};
228
229// A type-level function that takes first |n| list item from given TypeList.
230// E.g. TakeTypeListItem<3, TypeList<A, B, C, D>> is evaluated to
231// TypeList<A, B, C>.
232template <size_t n, typename List>
233using TakeTypeListItem = typename TakeTypeListItemImpl<n, List>::Type;
234
235// Used for ConcatTypeLists implementation.
236template <typename List1, typename List2>
237struct ConcatTypeListsImpl;
238
239template <typename... Types1, typename... Types2>
240struct ConcatTypeListsImpl<TypeList<Types1...>, TypeList<Types2...>> {
241 using Type = TypeList<Types1..., Types2...>;
242};
243
244// A type-level function that concats two TypeLists.
245template <typename List1, typename List2>
246using ConcatTypeLists = typename ConcatTypeListsImpl<List1, List2>::Type;
247
248// Used for MakeFunctionType implementation.
249template <typename R, typename ArgList>
250struct MakeFunctionTypeImpl;
251
252template <typename R, typename... Args>
253struct MakeFunctionTypeImpl<R, TypeList<Args...>> {
254 // MSVC 2013 doesn't support Type Alias of function types.
255 // Revisit this after we update it to newer version.
256 typedef R Type(Args...);
257};
258
259// A type-level function that constructs a function type that has |R| as its
260// return type and has TypeLists items as its arguments.
261template <typename R, typename ArgList>
262using MakeFunctionType = typename MakeFunctionTypeImpl<R, ArgList>::Type;
263
264// Used for ExtractArgs and ExtractReturnType.
265template <typename Signature>
266struct ExtractArgsImpl;
267
268template <typename R, typename... Args>
269struct ExtractArgsImpl<R(Args...)> {
270 using ReturnType = R;
271 using ArgsList = TypeList<Args...>;
272};
273
274// A type-level function that extracts function arguments into a TypeList.
275// E.g. ExtractArgs<R(A, B, C)> is evaluated to TypeList<A, B, C>.
276template <typename Signature>
277using ExtractArgs = typename ExtractArgsImpl<Signature>::ArgsList;
278
279// A type-level function that extracts the return type of a function.
280// E.g. ExtractReturnType<R(A, B, C)> is evaluated to R.
281template <typename Signature>
282using ExtractReturnType = typename ExtractArgsImpl<Signature>::ReturnType;
283
tzikc1db72652016-07-08 09:42:38284template <typename Callable,
285 typename Signature = decltype(&Callable::operator())>
286struct ExtractCallableRunTypeImpl;
287
288template <typename Callable, typename R, typename... Args>
tzikf98654b2017-12-02 03:28:58289struct ExtractCallableRunTypeImpl<Callable, R (Callable::*)(Args...)> {
290 using Type = R(Args...);
291};
292
293template <typename Callable, typename R, typename... Args>
294struct ExtractCallableRunTypeImpl<Callable, R (Callable::*)(Args...) const> {
tzikc1db72652016-07-08 09:42:38295 using Type = R(Args...);
296};
297
298// Evaluated to RunType of the given callable type.
299// Example:
300// auto f = [](int, char*) { return 0.1; };
301// ExtractCallableRunType<decltype(f)>
302// is evaluated to
303// double(int, char*);
304template <typename Callable>
305using ExtractCallableRunType =
306 typename ExtractCallableRunTypeImpl<Callable>::Type;
307
tzikf98654b2017-12-02 03:28:58308// IsCallableObject<Functor> is std::true_type if |Functor| has operator().
309// Otherwise, it's std::false_type.
tzikc1db72652016-07-08 09:42:38310// Example:
tzikf98654b2017-12-02 03:28:58311// IsCallableObject<void(*)()>::value is false.
tzikc1db72652016-07-08 09:42:38312//
313// struct Foo {};
tzikf98654b2017-12-02 03:28:58314// IsCallableObject<void(Foo::*)()>::value is false.
tzikc1db72652016-07-08 09:42:38315//
316// int i = 0;
tzikf98654b2017-12-02 03:28:58317// auto f = [i]() {};
318// IsCallableObject<decltype(f)>::value is false.
tzikc1db72652016-07-08 09:42:38319template <typename Functor, typename SFINAE = void>
tzikf98654b2017-12-02 03:28:58320struct IsCallableObject : std::false_type {};
tzikc1db72652016-07-08 09:42:38321
322template <typename Callable>
tzikf98654b2017-12-02 03:28:58323struct IsCallableObject<Callable, void_t<decltype(&Callable::operator())>>
324 : std::true_type {};
tzikc1db72652016-07-08 09:42:38325
Jan Wilken Dörriea33bc992020-03-24 17:45:31326// HasRefCountedTypeAsRawPtr inherits from true_type when any of the |Args| is a
327// raw pointer to a RefCounted type.
328template <typename... Ts>
329struct HasRefCountedTypeAsRawPtr
330 : disjunction<NeedsScopedRefptrButGetsRawPtr<Ts>...> {};
tzik401dd3672014-11-26 07:54:58331
[email protected]7296f2762011-11-21 19:23:44332// ForceVoidReturn<>
333//
334// Set of templates that support forcing the function return type to void.
335template <typename Sig>
336struct ForceVoidReturn;
337
tzikc82149922014-11-20 10:09:45338template <typename R, typename... Args>
339struct ForceVoidReturn<R(Args...)> {
tzik99de02b2016-07-01 05:54:12340 using RunType = void(Args...);
[email protected]fccef1552011-11-28 22:13:54341};
342
[email protected]7296f2762011-11-21 19:23:44343// FunctorTraits<>
344//
345// See description at top of file.
tzik6c92eab2016-11-25 15:56:36346template <typename Functor, typename SFINAE>
tzik99de02b2016-07-01 05:54:12347struct FunctorTraits;
348
tzikf98654b2017-12-02 03:28:58349// For empty callable types.
kylechar2255ccc2019-09-11 21:47:23350// This specialization is intended to allow binding captureless lambdas, based
351// on the fact that captureless lambdas are empty while capturing lambdas are
352// not. This also allows any functors as far as it's an empty class.
tzikf98654b2017-12-02 03:28:58353// Example:
354//
355// // Captureless lambdas are allowed.
356// []() {return 42;};
357//
358// // Capturing lambdas are *not* allowed.
359// int x;
360// [x]() {return x;};
361//
362// // Any empty class with operator() is allowed.
363// struct Foo {
364// void operator()() const {}
365// // No non-static member variable and no virtual functions.
366// };
tzikc1db72652016-07-08 09:42:38367template <typename Functor>
Jeremy Roman35a317432017-08-16 22:20:53368struct FunctorTraits<Functor,
tzikf98654b2017-12-02 03:28:58369 std::enable_if_t<IsCallableObject<Functor>::value &&
370 std::is_empty<Functor>::value>> {
tzikc1db72652016-07-08 09:42:38371 using RunType = ExtractCallableRunType<Functor>;
372 static constexpr bool is_method = false;
373 static constexpr bool is_nullable = false;
Sami Kyostila712b4e32020-04-27 16:51:08374 static constexpr bool is_callback = false;
tzikc1db72652016-07-08 09:42:38375
tzikf98654b2017-12-02 03:28:58376 template <typename RunFunctor, typename... RunArgs>
377 static ExtractReturnType<RunType> Invoke(RunFunctor&& functor,
378 RunArgs&&... args) {
379 return std::forward<RunFunctor>(functor)(std::forward<RunArgs>(args)...);
tzikc1db72652016-07-08 09:42:38380 }
381};
382
tzik99de02b2016-07-01 05:54:12383// For functions.
384template <typename R, typename... Args>
385struct FunctorTraits<R (*)(Args...)> {
386 using RunType = R(Args...);
387 static constexpr bool is_method = false;
tzikc1db72652016-07-08 09:42:38388 static constexpr bool is_nullable = true;
Sami Kyostila712b4e32020-04-27 16:51:08389 static constexpr bool is_callback = false;
tzik99de02b2016-07-01 05:54:12390
tzikd58a89232018-04-26 04:29:53391 template <typename Function, typename... RunArgs>
392 static R Invoke(Function&& function, RunArgs&&... args) {
393 return std::forward<Function>(function)(std::forward<RunArgs>(args)...);
tzik99de02b2016-07-01 05:54:12394 }
[email protected]7296f2762011-11-21 19:23:44395};
396
Gaurav Dholf6e3f592018-10-29 17:22:41397#if defined(OS_WIN) && !defined(ARCH_CPU_64_BITS)
tzik99de02b2016-07-01 05:54:12398
399// For functions.
400template <typename R, typename... Args>
401struct FunctorTraits<R(__stdcall*)(Args...)> {
402 using RunType = R(Args...);
403 static constexpr bool is_method = false;
tzikc1db72652016-07-08 09:42:38404 static constexpr bool is_nullable = true;
Sami Kyostila712b4e32020-04-27 16:51:08405 static constexpr bool is_callback = false;
tzik99de02b2016-07-01 05:54:12406
407 template <typename... RunArgs>
408 static R Invoke(R(__stdcall* function)(Args...), RunArgs&&... args) {
409 return function(std::forward<RunArgs>(args)...);
410 }
411};
412
413// For functions.
414template <typename R, typename... Args>
415struct FunctorTraits<R(__fastcall*)(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;
Sami Kyostila712b4e32020-04-27 16:51:08419 static constexpr bool is_callback = false;
tzik99de02b2016-07-01 05:54:12420
421 template <typename... RunArgs>
422 static R Invoke(R(__fastcall* function)(Args...), RunArgs&&... args) {
423 return function(std::forward<RunArgs>(args)...);
424 }
425};
426
Gaurav Dholf6e3f592018-10-29 17:22:41427#endif // defined(OS_WIN) && !defined(ARCH_CPU_64_BITS)
tzik99de02b2016-07-01 05:54:12428
Avi Drissman5b286372020-07-28 21:59:38429#if defined(OS_APPLE)
Sylvain Defresneec3270c2018-05-31 17:19:15430
431// Support for Objective-C blocks. There are two implementation depending
432// on whether Automated Reference Counting (ARC) is enabled. When ARC is
433// enabled, then the block itself can be bound as the compiler will ensure
434// its lifetime will be correctly managed. Otherwise, require the block to
435// be wrapped in a base::mac::ScopedBlock (via base::RetainBlock) that will
436// correctly manage the block lifetime.
437//
438// The two implementation ensure that the One Definition Rule (ODR) is not
439// broken (it is not possible to write a template base::RetainBlock that would
440// work correctly both with ARC enabled and disabled).
441
442#if HAS_FEATURE(objc_arc)
443
444template <typename R, typename... Args>
445struct FunctorTraits<R (^)(Args...)> {
446 using RunType = R(Args...);
447 static constexpr bool is_method = false;
448 static constexpr bool is_nullable = true;
Sami Kyostila712b4e32020-04-27 16:51:08449 static constexpr bool is_callback = false;
Sylvain Defresneec3270c2018-05-31 17:19:15450
451 template <typename BlockType, typename... RunArgs>
452 static R Invoke(BlockType&& block, RunArgs&&... args) {
453 // According to LLVM documentation (§ 6.3), "local variables of automatic
454 // storage duration do not have precise lifetime." Use objc_precise_lifetime
455 // to ensure that the Objective-C block is not deallocated until it has
456 // finished executing even if the Callback<> is destroyed during the block
457 // execution.
458 // https://clang.llvm.org/docs/AutomaticReferenceCounting.html#precise-lifetime-semantics
459 __attribute__((objc_precise_lifetime)) R (^scoped_block)(Args...) = block;
460 return scoped_block(std::forward<RunArgs>(args)...);
461 }
462};
463
464#else // HAS_FEATURE(objc_arc)
465
466template <typename R, typename... Args>
467struct FunctorTraits<base::mac::ScopedBlock<R (^)(Args...)>> {
468 using RunType = R(Args...);
469 static constexpr bool is_method = false;
470 static constexpr bool is_nullable = true;
Sami Kyostila712b4e32020-04-27 16:51:08471 static constexpr bool is_callback = false;
Sylvain Defresneec3270c2018-05-31 17:19:15472
473 template <typename BlockType, typename... RunArgs>
474 static R Invoke(BlockType&& block, RunArgs&&... args) {
475 // Copy the block to ensure that the Objective-C block is not deallocated
476 // until it has finished executing even if the Callback<> is destroyed
477 // during the block execution.
478 base::mac::ScopedBlock<R (^)(Args...)> scoped_block(block);
479 return scoped_block.get()(std::forward<RunArgs>(args)...);
480 }
481};
482
483#endif // HAS_FEATURE(objc_arc)
Avi Drissman5b286372020-07-28 21:59:38484#endif // defined(OS_APPLE)
Sylvain Defresneec3270c2018-05-31 17:19:15485
tzik99de02b2016-07-01 05:54:12486// For methods.
487template <typename R, typename Receiver, typename... Args>
488struct FunctorTraits<R (Receiver::*)(Args...)> {
489 using RunType = R(Receiver*, Args...);
490 static constexpr bool is_method = true;
tzikc1db72652016-07-08 09:42:38491 static constexpr bool is_nullable = true;
Sami Kyostila712b4e32020-04-27 16:51:08492 static constexpr bool is_callback = false;
tzik99de02b2016-07-01 05:54:12493
tzikd58a89232018-04-26 04:29:53494 template <typename Method, typename ReceiverPtr, typename... RunArgs>
495 static R Invoke(Method method,
tzik99de02b2016-07-01 05:54:12496 ReceiverPtr&& receiver_ptr,
497 RunArgs&&... args) {
tzik75851f42017-06-14 06:57:01498 return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
tzik99de02b2016-07-01 05:54:12499 }
500};
501
502// For const methods.
503template <typename R, typename Receiver, typename... Args>
504struct FunctorTraits<R (Receiver::*)(Args...) const> {
505 using RunType = R(const Receiver*, Args...);
506 static constexpr bool is_method = true;
tzikc1db72652016-07-08 09:42:38507 static constexpr bool is_nullable = true;
Sami Kyostila712b4e32020-04-27 16:51:08508 static constexpr bool is_callback = false;
tzik99de02b2016-07-01 05:54:12509
tzikd58a89232018-04-26 04:29:53510 template <typename Method, typename ReceiverPtr, typename... RunArgs>
511 static R Invoke(Method method,
tzik99de02b2016-07-01 05:54:12512 ReceiverPtr&& receiver_ptr,
513 RunArgs&&... args) {
tzik75851f42017-06-14 06:57:01514 return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
tzik99de02b2016-07-01 05:54:12515 }
516};
517
Sorin Jianu6bc2e352020-04-01 18:01:41518#if defined(OS_WIN) && !defined(ARCH_CPU_64_BITS)
519
520// For __stdcall methods.
521template <typename R, typename Receiver, typename... Args>
522struct FunctorTraits<R (__stdcall Receiver::*)(Args...)> {
523 using RunType = R(Receiver*, Args...);
524 static constexpr bool is_method = true;
525 static constexpr bool is_nullable = true;
Sami Kyostila712b4e32020-04-27 16:51:08526 static constexpr bool is_callback = false;
Sorin Jianu6bc2e352020-04-01 18:01:41527
528 template <typename Method, typename ReceiverPtr, typename... RunArgs>
529 static R Invoke(Method method,
530 ReceiverPtr&& receiver_ptr,
531 RunArgs&&... args) {
532 return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
533 }
534};
535
536// For __stdcall const methods.
537template <typename R, typename Receiver, typename... Args>
538struct FunctorTraits<R (__stdcall Receiver::*)(Args...) const> {
539 using RunType = R(const Receiver*, Args...);
540 static constexpr bool is_method = true;
541 static constexpr bool is_nullable = true;
Sami Kyostila712b4e32020-04-27 16:51:08542 static constexpr bool is_callback = false;
Sorin Jianu6bc2e352020-04-01 18:01:41543
544 template <typename Method, typename ReceiverPtr, typename... RunArgs>
545 static R Invoke(Method method,
546 ReceiverPtr&& receiver_ptr,
547 RunArgs&&... args) {
548 return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
549 }
550};
551
552#endif // defined(OS_WIN) && !defined(ARCH_CPU_64_BITS)
553
tzikd58a89232018-04-26 04:29:53554#ifdef __cpp_noexcept_function_type
555// noexcept makes a distinct function type in C++17.
556// I.e. `void(*)()` and `void(*)() noexcept` are same in pre-C++17, and
557// different in C++17.
558template <typename R, typename... Args>
559struct FunctorTraits<R (*)(Args...) noexcept> : FunctorTraits<R (*)(Args...)> {
560};
561
562template <typename R, typename Receiver, typename... Args>
563struct FunctorTraits<R (Receiver::*)(Args...) noexcept>
564 : FunctorTraits<R (Receiver::*)(Args...)> {};
565
566template <typename R, typename Receiver, typename... Args>
567struct FunctorTraits<R (Receiver::*)(Args...) const noexcept>
568 : FunctorTraits<R (Receiver::*)(Args...) const> {};
569#endif
570
tzik99de02b2016-07-01 05:54:12571// For IgnoreResults.
[email protected]7296f2762011-11-21 19:23:44572template <typename T>
tzik99de02b2016-07-01 05:54:12573struct FunctorTraits<IgnoreResultHelper<T>> : FunctorTraits<T> {
tzik3bc7779b2015-12-19 09:18:46574 using RunType =
tzik99de02b2016-07-01 05:54:12575 typename ForceVoidReturn<typename FunctorTraits<T>::RunType>::RunType;
576
577 template <typename IgnoreResultType, typename... RunArgs>
578 static void Invoke(IgnoreResultType&& ignore_result_helper,
579 RunArgs&&... args) {
tzikff54a5b152016-08-31 11:50:41580 FunctorTraits<T>::Invoke(
581 std::forward<IgnoreResultType>(ignore_result_helper).functor_,
582 std::forward<RunArgs>(args)...);
tzik99de02b2016-07-01 05:54:12583 }
[email protected]7296f2762011-11-21 19:23:44584};
585
tzikd4bb5b7d2017-08-28 19:08:52586// For OnceCallbacks.
587template <typename R, typename... Args>
588struct FunctorTraits<OnceCallback<R(Args...)>> {
589 using RunType = R(Args...);
590 static constexpr bool is_method = false;
591 static constexpr bool is_nullable = true;
Sami Kyostila712b4e32020-04-27 16:51:08592 static constexpr bool is_callback = true;
tzikd4bb5b7d2017-08-28 19:08:52593
594 template <typename CallbackType, typename... RunArgs>
595 static R Invoke(CallbackType&& callback, RunArgs&&... args) {
596 DCHECK(!callback.is_null());
597 return std::forward<CallbackType>(callback).Run(
598 std::forward<RunArgs>(args)...);
599 }
600};
601
602// For RepeatingCallbacks.
603template <typename R, typename... Args>
604struct FunctorTraits<RepeatingCallback<R(Args...)>> {
tzik99de02b2016-07-01 05:54:12605 using RunType = R(Args...);
606 static constexpr bool is_method = false;
tzikc1db72652016-07-08 09:42:38607 static constexpr bool is_nullable = true;
Sami Kyostila712b4e32020-04-27 16:51:08608 static constexpr bool is_callback = true;
tzik99de02b2016-07-01 05:54:12609
610 template <typename CallbackType, typename... RunArgs>
611 static R Invoke(CallbackType&& callback, RunArgs&&... args) {
612 DCHECK(!callback.is_null());
613 return std::forward<CallbackType>(callback).Run(
614 std::forward<RunArgs>(args)...);
615 }
[email protected]7296f2762011-11-21 19:23:44616};
617
tzikae4202e2017-07-31 10:41:54618template <typename Functor>
Jeremy Roman35a317432017-08-16 22:20:53619using MakeFunctorTraits = FunctorTraits<std::decay_t<Functor>>;
tzikae4202e2017-07-31 10:41:54620
[email protected]7296f2762011-11-21 19:23:44621// InvokeHelper<>
622//
tzik99de02b2016-07-01 05:54:12623// There are 2 logical InvokeHelper<> specializations: normal, WeakCalls.
[email protected]7296f2762011-11-21 19:23:44624//
625// The normal type just calls the underlying runnable.
626//
tzik99de02b2016-07-01 05:54:12627// WeakCalls need special syntax that is applied to the first argument to check
628// if they should no-op themselves.
tzikee248722016-06-01 08:22:51629template <bool is_weak_call, typename ReturnType>
[email protected]7296f2762011-11-21 19:23:44630struct InvokeHelper;
631
tzikee248722016-06-01 08:22:51632template <typename ReturnType>
633struct InvokeHelper<false, ReturnType> {
tzik99de02b2016-07-01 05:54:12634 template <typename Functor, typename... RunArgs>
635 static inline ReturnType MakeItSo(Functor&& functor, RunArgs&&... args) {
tzikae4202e2017-07-31 10:41:54636 using Traits = MakeFunctorTraits<Functor>;
tzik99de02b2016-07-01 05:54:12637 return Traits::Invoke(std::forward<Functor>(functor),
638 std::forward<RunArgs>(args)...);
[email protected]7296f2762011-11-21 19:23:44639 }
640};
641
tzikee248722016-06-01 08:22:51642template <typename ReturnType>
643struct InvokeHelper<true, ReturnType> {
[email protected]7296f2762011-11-21 19:23:44644 // WeakCalls are only supported for functions with a void return type.
Lei Zhang20b21af82020-08-10 18:31:58645 // Otherwise, the function result would be undefined if the WeakPtr<>
[email protected]7296f2762011-11-21 19:23:44646 // is invalidated.
tzik403cb6c2016-03-10 07:17:25647 static_assert(std::is_void<ReturnType>::value,
avi4ec0dff2015-11-24 14:26:24648 "weak_ptrs can only bind to methods without return values");
[email protected]c18b1052011-03-24 02:02:17649
tzik99de02b2016-07-01 05:54:12650 template <typename Functor, typename BoundWeakPtr, typename... RunArgs>
651 static inline void MakeItSo(Functor&& functor,
tzik33871d82016-07-14 12:12:06652 BoundWeakPtr&& weak_ptr,
tzik99de02b2016-07-01 05:54:12653 RunArgs&&... args) {
654 if (!weak_ptr)
655 return;
tzikae4202e2017-07-31 10:41:54656 using Traits = MakeFunctorTraits<Functor>;
tzik99de02b2016-07-01 05:54:12657 Traits::Invoke(std::forward<Functor>(functor),
658 std::forward<BoundWeakPtr>(weak_ptr),
659 std::forward<RunArgs>(args)...);
660 }
661};
[email protected]b38d3572011-02-15 01:27:38662
[email protected]7296f2762011-11-21 19:23:44663// Invoker<>
664//
665// See description at the top of the file.
tzikcaf1d84b2016-06-28 12:22:21666template <typename StorageType, typename UnboundRunType>
[email protected]7296f2762011-11-21 19:23:44667struct Invoker;
668
tzikcaf1d84b2016-06-28 12:22:21669template <typename StorageType, typename R, typename... UnboundArgs>
670struct Invoker<StorageType, R(UnboundArgs...)> {
Vladislav Kuzkokov6d208e12017-11-08 21:31:08671 static R RunOnce(BindStateBase* base,
tzik9bc6837b2018-06-28 20:20:47672 PassingType<UnboundArgs>... unbound_args) {
tzik27d1e312016-09-13 05:28:59673 // Local references to make debugger stepping easier. If in a debugger,
674 // you really want to warp ahead and step through the
675 // InvokeHelper<>::MakeItSo() call below.
676 StorageType* storage = static_cast<StorageType*>(base);
677 static constexpr size_t num_bound_args =
678 std::tuple_size<decltype(storage->bound_args_)>::value;
679 return RunImpl(std::move(storage->functor_),
680 std::move(storage->bound_args_),
Jeremy Roman84956fa2017-08-16 15:55:20681 std::make_index_sequence<num_bound_args>(),
tzik27d1e312016-09-13 05:28:59682 std::forward<UnboundArgs>(unbound_args)...);
683 }
684
tzik9bc6837b2018-06-28 20:20:47685 static R Run(BindStateBase* base, PassingType<UnboundArgs>... unbound_args) {
[email protected]7296f2762011-11-21 19:23:44686 // Local references to make debugger stepping easier. If in a debugger,
687 // you really want to warp ahead and step through the
688 // InvokeHelper<>::MakeItSo() call below.
tzikcaf1d84b2016-06-28 12:22:21689 const StorageType* storage = static_cast<StorageType*>(base);
690 static constexpr size_t num_bound_args =
691 std::tuple_size<decltype(storage->bound_args_)>::value;
Jeremy Roman84956fa2017-08-16 15:55:20692 return RunImpl(storage->functor_, storage->bound_args_,
693 std::make_index_sequence<num_bound_args>(),
tzikcaf1d84b2016-06-28 12:22:21694 std::forward<UnboundArgs>(unbound_args)...);
695 }
696
tzik99de02b2016-07-01 05:54:12697 private:
698 template <typename Functor, typename BoundArgsTuple, size_t... indices>
699 static inline R RunImpl(Functor&& functor,
tzikcaf1d84b2016-06-28 12:22:21700 BoundArgsTuple&& bound,
Jeremy Roman84956fa2017-08-16 15:55:20701 std::index_sequence<indices...>,
tzikcaf1d84b2016-06-28 12:22:21702 UnboundArgs&&... unbound_args) {
tzikae4202e2017-07-31 10:41:54703 static constexpr bool is_method = MakeFunctorTraits<Functor>::is_method;
tzikcaf1d84b2016-06-28 12:22:21704
Jeremy Roman35a317432017-08-16 22:20:53705 using DecayedArgsTuple = std::decay_t<BoundArgsTuple>;
tzikcaf1d84b2016-06-28 12:22:21706 static constexpr bool is_weak_call =
707 IsWeakMethod<is_method,
Jeremy Roman35a317432017-08-16 22:20:53708 std::tuple_element_t<indices, DecayedArgsTuple>...>();
tzikcaf1d84b2016-06-28 12:22:21709
tzikee248722016-06-01 08:22:51710 return InvokeHelper<is_weak_call, R>::MakeItSo(
tzik99de02b2016-07-01 05:54:12711 std::forward<Functor>(functor),
tzikf7c47572017-04-05 21:45:03712 Unwrap(std::get<indices>(std::forward<BoundArgsTuple>(bound)))...,
tzika43eff02016-03-09 05:46:05713 std::forward<UnboundArgs>(unbound_args)...);
[email protected]fccef1552011-11-28 22:13:54714 }
715};
716
tzikae4202e2017-07-31 10:41:54717// Extracts necessary type info from Functor and BoundArgs.
718// Used to implement MakeUnboundRunType, BindOnce and BindRepeating.
tzikcaf1d84b2016-06-28 12:22:21719template <typename Functor, typename... BoundArgs>
tzikae4202e2017-07-31 10:41:54720struct BindTypeHelper {
721 static constexpr size_t num_bounds = sizeof...(BoundArgs);
722 using FunctorTraits = MakeFunctorTraits<Functor>;
723
724 // Example:
725 // When Functor is `double (Foo::*)(int, const std::string&)`, and BoundArgs
726 // is a template pack of `Foo*` and `int16_t`:
727 // - RunType is `double(Foo*, int, const std::string&)`,
728 // - ReturnType is `double`,
729 // - RunParamsList is `TypeList<Foo*, int, const std::string&>`,
730 // - BoundParamsList is `TypeList<Foo*, int>`,
731 // - UnboundParamsList is `TypeList<const std::string&>`,
732 // - BoundArgsList is `TypeList<Foo*, int16_t>`,
733 // - UnboundRunType is `double(const std::string&)`.
734 using RunType = typename FunctorTraits::RunType;
tzikcaf1d84b2016-06-28 12:22:21735 using ReturnType = ExtractReturnType<RunType>;
tzikae4202e2017-07-31 10:41:54736
737 using RunParamsList = ExtractArgs<RunType>;
738 using BoundParamsList = TakeTypeListItem<num_bounds, RunParamsList>;
739 using UnboundParamsList = DropTypeListItem<num_bounds, RunParamsList>;
740
741 using BoundArgsList = TypeList<BoundArgs...>;
742
743 using UnboundRunType = MakeFunctionType<ReturnType, UnboundParamsList>;
tzikcaf1d84b2016-06-28 12:22:21744};
tzikae4202e2017-07-31 10:41:54745
tzikc1db72652016-07-08 09:42:38746template <typename Functor>
Jeremy Roman35a317432017-08-16 22:20:53747std::enable_if_t<FunctorTraits<Functor>::is_nullable, bool> IsNull(
748 const Functor& functor) {
tzikc1db72652016-07-08 09:42:38749 return !functor;
750}
751
752template <typename Functor>
Jeremy Roman35a317432017-08-16 22:20:53753std::enable_if_t<!FunctorTraits<Functor>::is_nullable, bool> IsNull(
754 const Functor&) {
tzikc1db72652016-07-08 09:42:38755 return false;
756}
tzikcaf1d84b2016-06-28 12:22:21757
tzik9697d49e2018-08-02 13:35:19758// Used by QueryCancellationTraits below.
tzik6c92eab2016-11-25 15:56:36759template <typename Functor, typename BoundArgsTuple, size_t... indices>
tzik9697d49e2018-08-02 13:35:19760bool QueryCancellationTraitsImpl(BindStateBase::CancellationQueryMode mode,
761 const Functor& functor,
762 const BoundArgsTuple& bound_args,
763 std::index_sequence<indices...>) {
764 switch (mode) {
765 case BindStateBase::IS_CANCELLED:
766 return CallbackCancellationTraits<Functor, BoundArgsTuple>::IsCancelled(
767 functor, std::get<indices>(bound_args)...);
768 case BindStateBase::MAYBE_VALID:
769 return CallbackCancellationTraits<Functor, BoundArgsTuple>::MaybeValid(
770 functor, std::get<indices>(bound_args)...);
771 }
772 NOTREACHED();
tzik6c92eab2016-11-25 15:56:36773}
tzik59aa6bb12016-09-08 10:58:53774
tzik6c92eab2016-11-25 15:56:36775// Relays |base| to corresponding CallbackCancellationTraits<>::Run(). Returns
776// true if the callback |base| represents is canceled.
777template <typename BindStateType>
tzik9697d49e2018-08-02 13:35:19778bool QueryCancellationTraits(const BindStateBase* base,
779 BindStateBase::CancellationQueryMode mode) {
tzik6c92eab2016-11-25 15:56:36780 const BindStateType* storage = static_cast<const BindStateType*>(base);
781 static constexpr size_t num_bound_args =
782 std::tuple_size<decltype(storage->bound_args_)>::value;
tzik9697d49e2018-08-02 13:35:19783 return QueryCancellationTraitsImpl(
784 mode, storage->functor_, storage->bound_args_,
Nicolas Ouellet-payeur40f8e9a2018-07-30 16:26:48785 std::make_index_sequence<num_bound_args>());
Nicolas Ouellet-payeur40f8e9a2018-07-30 16:26:48786}
787
tzikefea4f52018-08-02 15:20:46788// The base case of BanUnconstructedRefCountedReceiver that checks nothing.
789template <typename Functor, typename Receiver, typename... Unused>
790std::enable_if_t<
791 !(MakeFunctorTraits<Functor>::is_method &&
792 std::is_pointer<std::decay_t<Receiver>>::value &&
793 IsRefCountedType<std::remove_pointer_t<std::decay_t<Receiver>>>::value)>
794BanUnconstructedRefCountedReceiver(const Receiver& receiver, Unused&&...) {}
795
796template <typename Functor>
797void BanUnconstructedRefCountedReceiver() {}
798
799// Asserts that Callback is not the first owner of a ref-counted receiver.
800template <typename Functor, typename Receiver, typename... Unused>
801std::enable_if_t<
802 MakeFunctorTraits<Functor>::is_method &&
803 std::is_pointer<std::decay_t<Receiver>>::value &&
804 IsRefCountedType<std::remove_pointer_t<std::decay_t<Receiver>>>::value>
805BanUnconstructedRefCountedReceiver(const Receiver& receiver, Unused&&...) {
806 DCHECK(receiver);
807
808 // It's error prone to make the implicit first reference to ref-counted types.
809 // In the example below, base::BindOnce() makes the implicit first reference
810 // to the ref-counted Foo. If PostTask() failed or the posted task ran fast
811 // enough, the newly created instance can be destroyed before |oo| makes
812 // another reference.
813 // Foo::Foo() {
814 // base::PostTask(FROM_HERE, base::BindOnce(&Foo::Bar, this));
815 // }
816 //
817 // scoped_refptr<Foo> oo = new Foo();
818 //
819 // Instead of doing like above, please consider adding a static constructor,
820 // and keep the first reference alive explicitly.
821 // // static
822 // scoped_refptr<Foo> Foo::Create() {
823 // auto foo = base::WrapRefCounted(new Foo());
824 // base::PostTask(FROM_HERE, base::BindOnce(&Foo::Bar, foo));
825 // return foo;
826 // }
827 //
828 // Foo::Foo() {}
829 //
830 // scoped_refptr<Foo> oo = Foo::Create();
831 DCHECK(receiver->HasAtLeastOneRef())
kylechar2255ccc2019-09-11 21:47:23832 << "base::Bind{Once,Repeating}() refuses to create the first reference "
833 "to ref-counted objects. That typically happens around PostTask() in "
834 "their constructor, and such objects can be destroyed before `new` "
835 "returns if the task resolves fast enough.";
tzikefea4f52018-08-02 15:20:46836}
837
[email protected]7296f2762011-11-21 19:23:44838// BindState<>
839//
tzik99de02b2016-07-01 05:54:12840// This stores all the state passed into Bind().
841template <typename Functor, typename... BoundArgs>
842struct BindState final : BindStateBase {
Jan Wilken Dörriea33bc992020-03-24 17:45:31843 using IsCancellable = bool_constant<
tzik6c92eab2016-11-25 15:56:36844 CallbackCancellationTraits<Functor,
845 std::tuple<BoundArgs...>>::is_cancellable>;
tzikbfe66122016-07-08 14:14:01846 template <typename ForwardFunctor, typename... ForwardBoundArgs>
tzikefea4f52018-08-02 15:20:46847 static BindState* Create(BindStateBase::InvokeFuncStorage invoke_func,
848 ForwardFunctor&& functor,
849 ForwardBoundArgs&&... bound_args) {
850 // Ban ref counted receivers that were not yet fully constructed to avoid
851 // a common pattern of racy situation.
852 BanUnconstructedRefCountedReceiver<ForwardFunctor>(bound_args...);
853
854 // IsCancellable is std::false_type if
855 // CallbackCancellationTraits<>::IsCancelled returns always false.
856 // Otherwise, it's std::true_type.
857 return new BindState(IsCancellable{}, invoke_func,
858 std::forward<ForwardFunctor>(functor),
859 std::forward<ForwardBoundArgs>(bound_args)...);
860 }
tzik1fdcca32016-09-14 07:15:00861
862 Functor functor_;
863 std::tuple<BoundArgs...> bound_args_;
864
865 private:
Sami Kyostila712b4e32020-04-27 16:51:08866 static constexpr bool is_nested_callback =
867 internal::MakeFunctorTraits<Functor>::is_callback;
868
tzik1fdcca32016-09-14 07:15:00869 template <typename ForwardFunctor, typename... ForwardBoundArgs>
870 explicit BindState(std::true_type,
871 BindStateBase::InvokeFuncStorage invoke_func,
872 ForwardFunctor&& functor,
873 ForwardBoundArgs&&... bound_args)
tzik6c92eab2016-11-25 15:56:36874 : BindStateBase(invoke_func,
875 &Destroy,
tzik9697d49e2018-08-02 13:35:19876 &QueryCancellationTraits<BindState>),
tzikff54a5b152016-08-31 11:50:41877 functor_(std::forward<ForwardFunctor>(functor)),
tzik99de02b2016-07-01 05:54:12878 bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
Sami Kyostila712b4e32020-04-27 16:51:08879 // We check the validity of nested callbacks (e.g., Bind(callback, ...)) in
880 // release builds to avoid null pointers from ending up in posted tasks,
881 // causing hard-to-diagnose crashes. Ideally we'd do this for all functors
882 // here, but that would have a large binary size impact.
883 if (is_nested_callback) {
884 CHECK(!IsNull(functor_));
885 } else {
886 DCHECK(!IsNull(functor_));
887 }
tzik99de02b2016-07-01 05:54:12888 }
[email protected]7296f2762011-11-21 19:23:44889
tzik1fdcca32016-09-14 07:15:00890 template <typename ForwardFunctor, typename... ForwardBoundArgs>
891 explicit BindState(std::false_type,
892 BindStateBase::InvokeFuncStorage invoke_func,
893 ForwardFunctor&& functor,
894 ForwardBoundArgs&&... bound_args)
895 : BindStateBase(invoke_func, &Destroy),
896 functor_(std::forward<ForwardFunctor>(functor)),
897 bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
Sami Kyostila712b4e32020-04-27 16:51:08898 // See above for CHECK/DCHECK rationale.
899 if (is_nested_callback) {
900 CHECK(!IsNull(functor_));
901 } else {
902 DCHECK(!IsNull(functor_));
903 }
tzik1fdcca32016-09-14 07:15:00904 }
dmichael7d09007e2014-12-18 22:30:11905
Chris Watkins091d6292017-12-13 04:25:58906 ~BindState() = default;
taptede7e804c2015-05-14 08:03:32907
tzik30e0c312016-09-21 08:06:54908 static void Destroy(const BindStateBase* self) {
909 delete static_cast<const BindState*>(self);
taptede7e804c2015-05-14 08:03:32910 }
[email protected]fccef1552011-11-28 22:13:54911};
912
tzik99de02b2016-07-01 05:54:12913// Used to implement MakeBindStateType.
914template <bool is_method, typename Functor, typename... BoundArgs>
915struct MakeBindStateTypeImpl;
916
917template <typename Functor, typename... BoundArgs>
918struct MakeBindStateTypeImpl<false, Functor, BoundArgs...> {
Jeremy Roman35a317432017-08-16 22:20:53919 static_assert(!HasRefCountedTypeAsRawPtr<std::decay_t<BoundArgs>...>::value,
tzik99de02b2016-07-01 05:54:12920 "A parameter is a refcounted type and needs scoped_refptr.");
Jeremy Roman35a317432017-08-16 22:20:53921 using Type = BindState<std::decay_t<Functor>, std::decay_t<BoundArgs>...>;
tzik99de02b2016-07-01 05:54:12922};
923
924template <typename Functor>
925struct MakeBindStateTypeImpl<true, Functor> {
Jeremy Roman35a317432017-08-16 22:20:53926 using Type = BindState<std::decay_t<Functor>>;
tzik99de02b2016-07-01 05:54:12927};
928
929template <typename Functor, typename Receiver, typename... BoundArgs>
930struct MakeBindStateTypeImpl<true, Functor, Receiver, BoundArgs...> {
tzik99de02b2016-07-01 05:54:12931 private:
Jeremy Roman35a317432017-08-16 22:20:53932 using DecayedReceiver = std::decay_t<Receiver>;
tzik99de02b2016-07-01 05:54:12933
tzik4625ac612018-02-28 09:43:55934 static_assert(!std::is_array<std::remove_reference_t<Receiver>>::value,
935 "First bound argument to a method cannot be an array.");
936 static_assert(
937 !std::is_pointer<DecayedReceiver>::value ||
938 IsRefCountedType<std::remove_pointer_t<DecayedReceiver>>::value,
939 "Receivers may not be raw pointers. If using a raw pointer here is safe"
940 " and has no lifetime concerns, use base::Unretained() and document why"
941 " it's safe.");
942 static_assert(!HasRefCountedTypeAsRawPtr<std::decay_t<BoundArgs>...>::value,
943 "A parameter is a refcounted type and needs scoped_refptr.");
944
tzik99de02b2016-07-01 05:54:12945 public:
946 using Type = BindState<
Jeremy Roman35a317432017-08-16 22:20:53947 std::decay_t<Functor>,
948 std::conditional_t<std::is_pointer<DecayedReceiver>::value,
949 scoped_refptr<std::remove_pointer_t<DecayedReceiver>>,
950 DecayedReceiver>,
951 std::decay_t<BoundArgs>...>;
tzik99de02b2016-07-01 05:54:12952};
953
954template <typename Functor, typename... BoundArgs>
tzikae4202e2017-07-31 10:41:54955using MakeBindStateType =
956 typename MakeBindStateTypeImpl<MakeFunctorTraits<Functor>::is_method,
957 Functor,
958 BoundArgs...>::Type;
tzik99de02b2016-07-01 05:54:12959
[email protected]b38d3572011-02-15 01:27:38960} // namespace internal
tzikcaf1d84b2016-06-28 12:22:21961
Peter Kastinga85265e32018-02-15 08:30:23962// An injection point to control |this| pointer behavior on a method invocation.
963// If IsWeakReceiver<> is true_type for |T| and |T| is used for a receiver of a
964// method, base::Bind cancels the method invocation if the receiver is tested as
965// false.
966// E.g. Foo::bar() is not called:
967// struct Foo : base::SupportsWeakPtr<Foo> {
968// void bar() {}
969// };
970//
971// WeakPtr<Foo> oo = nullptr;
kylechar2255ccc2019-09-11 21:47:23972// base::BindOnce(&Foo::bar, oo).Run();
Peter Kastinga85265e32018-02-15 08:30:23973template <typename T>
974struct IsWeakReceiver : std::false_type {};
975
976template <typename T>
jdoerriec79c2fa22019-02-26 12:35:03977struct IsWeakReceiver<std::reference_wrapper<T>> : IsWeakReceiver<T> {};
Peter Kastinga85265e32018-02-15 08:30:23978
979template <typename T>
980struct IsWeakReceiver<WeakPtr<T>> : std::true_type {};
981
982// An injection point to control how bound objects passed to the target
983// function. BindUnwrapTraits<>::Unwrap() is called for each bound objects right
984// before the target function is invoked.
985template <typename>
986struct BindUnwrapTraits {
987 template <typename T>
988 static T&& Unwrap(T&& o) {
989 return std::forward<T>(o);
990 }
991};
992
993template <typename T>
994struct BindUnwrapTraits<internal::UnretainedWrapper<T>> {
995 static T* Unwrap(const internal::UnretainedWrapper<T>& o) { return o.get(); }
996};
997
998template <typename T>
jdoerriec79c2fa22019-02-26 12:35:03999struct BindUnwrapTraits<std::reference_wrapper<T>> {
1000 static T& Unwrap(std::reference_wrapper<T> o) { return o.get(); }
Peter Kastinga85265e32018-02-15 08:30:231001};
1002
1003template <typename T>
1004struct BindUnwrapTraits<internal::RetainedRefWrapper<T>> {
1005 static T* Unwrap(const internal::RetainedRefWrapper<T>& o) { return o.get(); }
1006};
1007
Marijn Kruisselbrinkc1e775f2019-12-19 01:24:221008template <typename T, typename Deleter>
1009struct BindUnwrapTraits<internal::OwnedWrapper<T, Deleter>> {
1010 static T* Unwrap(const internal::OwnedWrapper<T, Deleter>& o) {
1011 return o.get();
1012 }
Peter Kastinga85265e32018-02-15 08:30:231013};
1014
1015template <typename T>
1016struct BindUnwrapTraits<internal::PassedWrapper<T>> {
1017 static T Unwrap(const internal::PassedWrapper<T>& o) { return o.Take(); }
1018};
1019
tzikc44f8102018-07-24 09:49:191020#if defined(OS_WIN)
1021template <typename T>
1022struct BindUnwrapTraits<Microsoft::WRL::ComPtr<T>> {
1023 static T* Unwrap(const Microsoft::WRL::ComPtr<T>& ptr) { return ptr.Get(); }
1024};
1025#endif
1026
Peter Kastinga85265e32018-02-15 08:30:231027// CallbackCancellationTraits allows customization of Callback's cancellation
1028// semantics. By default, callbacks are not cancellable. A specialization should
1029// set is_cancellable = true and implement an IsCancelled() that returns if the
1030// callback should be cancelled.
1031template <typename Functor, typename BoundArgsTuple, typename SFINAE>
1032struct CallbackCancellationTraits {
1033 static constexpr bool is_cancellable = false;
1034};
1035
1036// Specialization for method bound to weak pointer receiver.
1037template <typename Functor, typename... BoundArgs>
1038struct CallbackCancellationTraits<
1039 Functor,
1040 std::tuple<BoundArgs...>,
1041 std::enable_if_t<
1042 internal::IsWeakMethod<internal::FunctorTraits<Functor>::is_method,
1043 BoundArgs...>::value>> {
1044 static constexpr bool is_cancellable = true;
1045
1046 template <typename Receiver, typename... Args>
1047 static bool IsCancelled(const Functor&,
1048 const Receiver& receiver,
1049 const Args&...) {
1050 return !receiver;
1051 }
Nicolas Ouellet-payeur40f8e9a2018-07-30 16:26:481052
1053 template <typename Receiver, typename... Args>
1054 static bool MaybeValid(const Functor&,
1055 const Receiver& receiver,
1056 const Args&...) {
1057 return receiver.MaybeValid();
1058 }
Peter Kastinga85265e32018-02-15 08:30:231059};
1060
1061// Specialization for a nested bind.
1062template <typename Signature, typename... BoundArgs>
1063struct CallbackCancellationTraits<OnceCallback<Signature>,
1064 std::tuple<BoundArgs...>> {
1065 static constexpr bool is_cancellable = true;
1066
1067 template <typename Functor>
1068 static bool IsCancelled(const Functor& functor, const BoundArgs&...) {
1069 return functor.IsCancelled();
1070 }
Nicolas Ouellet-payeur40f8e9a2018-07-30 16:26:481071
1072 template <typename Functor>
1073 static bool MaybeValid(const Functor& functor, const BoundArgs&...) {
1074 return functor.MaybeValid();
1075 }
Peter Kastinga85265e32018-02-15 08:30:231076};
1077
1078template <typename Signature, typename... BoundArgs>
1079struct CallbackCancellationTraits<RepeatingCallback<Signature>,
1080 std::tuple<BoundArgs...>> {
1081 static constexpr bool is_cancellable = true;
1082
1083 template <typename Functor>
1084 static bool IsCancelled(const Functor& functor, const BoundArgs&...) {
1085 return functor.IsCancelled();
1086 }
Nicolas Ouellet-payeur40f8e9a2018-07-30 16:26:481087
1088 template <typename Functor>
1089 static bool MaybeValid(const Functor& functor, const BoundArgs&...) {
1090 return functor.MaybeValid();
1091 }
Peter Kastinga85265e32018-02-15 08:30:231092};
1093
tzikcaf1d84b2016-06-28 12:22:211094// Returns a RunType of bound functor.
1095// E.g. MakeUnboundRunType<R(A, B, C), A, B> is evaluated to R(C).
1096template <typename Functor, typename... BoundArgs>
1097using MakeUnboundRunType =
tzikae4202e2017-07-31 10:41:541098 typename internal::BindTypeHelper<Functor, BoundArgs...>::UnboundRunType;
tzikcaf1d84b2016-06-28 12:22:211099
[email protected]b38d3572011-02-15 01:27:381100} // namespace base
1101
1102#endif // BASE_BIND_INTERNAL_H_