blob: deda4e72abecb081a75500b9a0826e740296973f [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
jdoerrie5c4dc4e2019-02-01 18:02:3310#include <tuple>
vmpstrc52317f2015-11-18 08:43:2611#include <type_traits>
Jeremy Roman84956fa2017-08-16 15:55:2012#include <utility>
vmpstrc52317f2015-11-18 08:43:2613
Sebastien Marchand6d0558fd2019-01-25 16:49:3714#include "base/bind.h"
[email protected]59eff912011-02-18 23:29:3115#include "base/callback_internal.h"
Sylvain Defresneec3270c2018-05-31 17:19:1516#include "base/compiler_specific.h"
[email protected]8217d4542011-10-01 06:31:4117#include "base/memory/raw_scoped_refptr_mismatch_checker.h"
[email protected]93540582011-05-16 22:35:1418#include "base/memory/weak_ptr.h"
[email protected]b38d3572011-02-15 01:27:3819#include "base/template_util.h"
[email protected]054ac7542011-02-27 01:25:5920#include "build/build_config.h"
21
Sylvain Defresneec3270c2018-05-31 17:19:1522#if defined(OS_MACOSX) && !HAS_FEATURE(objc_arc)
23#include "base/mac/scoped_block.h"
24#endif
25
[email protected]24292642012-07-12 20:06:4026// See base/callback.h for user documentation.
27//
28//
[email protected]7296f2762011-11-21 19:23:4429// CONCEPTS:
tzik99de02b2016-07-01 05:54:1230// Functor -- A movable type representing something that should be called.
31// All function pointers and Callback<> are functors even if the
32// invocation syntax differs.
[email protected]7296f2762011-11-21 19:23:4433// RunType -- A function type (as opposed to function _pointer_ type) for
tzik99de02b2016-07-01 05:54:1234// a Callback<>::Run(). Usually just a convenience typedef.
tzikce3ecf82015-12-15 06:41:4935// (Bound)Args -- A set of types that stores the arguments.
[email protected]b38d3572011-02-15 01:27:3836//
[email protected]7296f2762011-11-21 19:23:4437// Types:
[email protected]7296f2762011-11-21 19:23:4438// ForceVoidReturn<> -- Helper class for translating function signatures to
39// equivalent forms with a "void" return type.
tzik99de02b2016-07-01 05:54:1240// FunctorTraits<> -- Type traits used to determine the correct RunType and
41// invocation manner for a Functor. This is where function
[email protected]7296f2762011-11-21 19:23:4442// signature adapters are applied.
tzik99de02b2016-07-01 05:54:1243// InvokeHelper<> -- Take a Functor + arguments and actully invokes it.
tzik8ce65702015-02-05 19:11:2644// Handle the differing syntaxes needed for WeakPtr<>
tzik99de02b2016-07-01 05:54:1245// support. This is separate from Invoker to avoid creating
46// multiple version of Invoker<>.
47// Invoker<> -- Unwraps the curried parameters and executes the Functor.
[email protected]7296f2762011-11-21 19:23:4448// BindState<> -- Stores the curried parameters, and is the main entry point
tzik99de02b2016-07-01 05:54:1249// into the Bind() system.
[email protected]4346ef912011-02-19 00:52:1550
tzikc44f8102018-07-24 09:49:1951#if defined(OS_WIN)
52namespace Microsoft {
53namespace WRL {
54template <typename>
55class ComPtr;
56} // namespace WRL
57} // namespace Microsoft
58#endif
59
Peter Kastinga85265e32018-02-15 08:30:2360namespace base {
61
62template <typename T>
63struct IsWeakReceiver;
64
65template <typename>
66struct BindUnwrapTraits;
67
68template <typename Functor, typename BoundArgsTuple, typename SFINAE = void>
69struct CallbackCancellationTraits;
70
71namespace internal {
72
73template <typename Functor, typename SFINAE = void>
74struct FunctorTraits;
75
76template <typename T>
77class UnretainedWrapper {
78 public:
79 explicit UnretainedWrapper(T* o) : ptr_(o) {}
80 T* get() const { return ptr_; }
81
82 private:
83 T* ptr_;
84};
85
86template <typename T>
87class ConstRefWrapper {
88 public:
89 explicit ConstRefWrapper(const T& o) : ptr_(&o) {}
90 const T& get() const { return *ptr_; }
91
92 private:
93 const T* ptr_;
94};
95
96template <typename T>
97class RetainedRefWrapper {
98 public:
99 explicit RetainedRefWrapper(T* o) : ptr_(o) {}
100 explicit RetainedRefWrapper(scoped_refptr<T> o) : ptr_(std::move(o)) {}
101 T* get() const { return ptr_.get(); }
102
103 private:
104 scoped_refptr<T> ptr_;
105};
106
107template <typename T>
108struct IgnoreResultHelper {
109 explicit IgnoreResultHelper(T functor) : functor_(std::move(functor)) {}
110 explicit operator bool() const { return !!functor_; }
111
112 T functor_;
113};
114
115// An alternate implementation is to avoid the destructive copy, and instead
116// specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to
117// a class that is essentially a std::unique_ptr<>.
118//
119// The current implementation has the benefit though of leaving ParamTraits<>
120// fully in callback_internal.h as well as avoiding type conversions during
121// storage.
122template <typename T>
123class OwnedWrapper {
124 public:
125 explicit OwnedWrapper(T* o) : ptr_(o) {}
126 ~OwnedWrapper() { delete ptr_; }
127 T* get() const { return ptr_; }
128 OwnedWrapper(OwnedWrapper&& other) {
129 ptr_ = other.ptr_;
130 other.ptr_ = NULL;
131 }
132
133 private:
134 mutable T* ptr_;
135};
136
137// PassedWrapper is a copyable adapter for a scoper that ignores const.
138//
139// It is needed to get around the fact that Bind() takes a const reference to
140// all its arguments. Because Bind() takes a const reference to avoid
141// unnecessary copies, it is incompatible with movable-but-not-copyable
142// types; doing a destructive "move" of the type into Bind() would violate
143// the const correctness.
144//
145// This conundrum cannot be solved without either C++11 rvalue references or
146// a O(2^n) blowup of Bind() templates to handle each combination of regular
147// types and movable-but-not-copyable types. Thus we introduce a wrapper type
148// that is copyable to transmit the correct type information down into
149// BindState<>. Ignoring const in this type makes sense because it is only
150// created when we are explicitly trying to do a destructive move.
151//
152// Two notes:
153// 1) PassedWrapper supports any type that has a move constructor, however
154// the type will need to be specifically whitelisted in order for it to be
155// bound to a Callback. We guard this explicitly at the call of Passed()
156// to make for clear errors. Things not given to Passed() will be forwarded
157// and stored by value which will not work for general move-only types.
158// 2) is_valid_ is distinct from NULL because it is valid to bind a "NULL"
159// scoper to a Callback and allow the Callback to execute once.
160template <typename T>
161class PassedWrapper {
162 public:
163 explicit PassedWrapper(T&& scoper)
164 : is_valid_(true), scoper_(std::move(scoper)) {}
165 PassedWrapper(PassedWrapper&& other)
166 : is_valid_(other.is_valid_), scoper_(std::move(other.scoper_)) {}
167 T Take() const {
168 CHECK(is_valid_);
169 is_valid_ = false;
170 return std::move(scoper_);
171 }
172
173 private:
174 mutable bool is_valid_;
175 mutable T scoper_;
176};
177
178template <typename T>
179using Unwrapper = BindUnwrapTraits<std::decay_t<T>>;
180
181template <typename T>
Peter Kastingc2f8749bf2018-03-31 03:32:37182decltype(auto) Unwrap(T&& o) {
Peter Kastinga85265e32018-02-15 08:30:23183 return Unwrapper<T>::Unwrap(std::forward<T>(o));
184}
185
186// IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a
187// method. It is used internally by Bind() to select the correct
188// InvokeHelper that will no-op itself in the event the WeakPtr<> for
189// the target object is invalidated.
190//
191// The first argument should be the type of the object that will be received by
192// the method.
193template <bool is_method, typename... Args>
194struct IsWeakMethod : std::false_type {};
195
196template <typename T, typename... Args>
197struct IsWeakMethod<true, T, Args...> : IsWeakReceiver<T> {};
198
199// Packs a list of types to hold them in a single type.
200template <typename... Types>
201struct TypeList {};
202
203// Used for DropTypeListItem implementation.
204template <size_t n, typename List>
205struct DropTypeListItemImpl;
206
207// Do not use enable_if and SFINAE here to avoid MSVC2013 compile failure.
208template <size_t n, typename T, typename... List>
209struct DropTypeListItemImpl<n, TypeList<T, List...>>
210 : DropTypeListItemImpl<n - 1, TypeList<List...>> {};
211
212template <typename T, typename... List>
213struct DropTypeListItemImpl<0, TypeList<T, List...>> {
214 using Type = TypeList<T, List...>;
215};
216
217template <>
218struct DropTypeListItemImpl<0, TypeList<>> {
219 using Type = TypeList<>;
220};
221
222// A type-level function that drops |n| list item from given TypeList.
223template <size_t n, typename List>
224using DropTypeListItem = typename DropTypeListItemImpl<n, List>::Type;
225
226// Used for TakeTypeListItem implementation.
227template <size_t n, typename List, typename... Accum>
228struct TakeTypeListItemImpl;
229
230// Do not use enable_if and SFINAE here to avoid MSVC2013 compile failure.
231template <size_t n, typename T, typename... List, typename... Accum>
232struct TakeTypeListItemImpl<n, TypeList<T, List...>, Accum...>
233 : TakeTypeListItemImpl<n - 1, TypeList<List...>, Accum..., T> {};
234
235template <typename T, typename... List, typename... Accum>
236struct TakeTypeListItemImpl<0, TypeList<T, List...>, Accum...> {
237 using Type = TypeList<Accum...>;
238};
239
240template <typename... Accum>
241struct TakeTypeListItemImpl<0, TypeList<>, Accum...> {
242 using Type = TypeList<Accum...>;
243};
244
245// A type-level function that takes first |n| list item from given TypeList.
246// E.g. TakeTypeListItem<3, TypeList<A, B, C, D>> is evaluated to
247// TypeList<A, B, C>.
248template <size_t n, typename List>
249using TakeTypeListItem = typename TakeTypeListItemImpl<n, List>::Type;
250
251// Used for ConcatTypeLists implementation.
252template <typename List1, typename List2>
253struct ConcatTypeListsImpl;
254
255template <typename... Types1, typename... Types2>
256struct ConcatTypeListsImpl<TypeList<Types1...>, TypeList<Types2...>> {
257 using Type = TypeList<Types1..., Types2...>;
258};
259
260// A type-level function that concats two TypeLists.
261template <typename List1, typename List2>
262using ConcatTypeLists = typename ConcatTypeListsImpl<List1, List2>::Type;
263
264// Used for MakeFunctionType implementation.
265template <typename R, typename ArgList>
266struct MakeFunctionTypeImpl;
267
268template <typename R, typename... Args>
269struct MakeFunctionTypeImpl<R, TypeList<Args...>> {
270 // MSVC 2013 doesn't support Type Alias of function types.
271 // Revisit this after we update it to newer version.
272 typedef R Type(Args...);
273};
274
275// A type-level function that constructs a function type that has |R| as its
276// return type and has TypeLists items as its arguments.
277template <typename R, typename ArgList>
278using MakeFunctionType = typename MakeFunctionTypeImpl<R, ArgList>::Type;
279
280// Used for ExtractArgs and ExtractReturnType.
281template <typename Signature>
282struct ExtractArgsImpl;
283
284template <typename R, typename... Args>
285struct ExtractArgsImpl<R(Args...)> {
286 using ReturnType = R;
287 using ArgsList = TypeList<Args...>;
288};
289
290// A type-level function that extracts function arguments into a TypeList.
291// E.g. ExtractArgs<R(A, B, C)> is evaluated to TypeList<A, B, C>.
292template <typename Signature>
293using ExtractArgs = typename ExtractArgsImpl<Signature>::ArgsList;
294
295// A type-level function that extracts the return type of a function.
296// E.g. ExtractReturnType<R(A, B, C)> is evaluated to R.
297template <typename Signature>
298using ExtractReturnType = typename ExtractArgsImpl<Signature>::ReturnType;
299
tzikc1db72652016-07-08 09:42:38300template <typename Callable,
301 typename Signature = decltype(&Callable::operator())>
302struct ExtractCallableRunTypeImpl;
303
304template <typename Callable, typename R, typename... Args>
tzikf98654b2017-12-02 03:28:58305struct ExtractCallableRunTypeImpl<Callable, R (Callable::*)(Args...)> {
306 using Type = R(Args...);
307};
308
309template <typename Callable, typename R, typename... Args>
310struct ExtractCallableRunTypeImpl<Callable, R (Callable::*)(Args...) const> {
tzikc1db72652016-07-08 09:42:38311 using Type = R(Args...);
312};
313
314// Evaluated to RunType of the given callable type.
315// Example:
316// auto f = [](int, char*) { return 0.1; };
317// ExtractCallableRunType<decltype(f)>
318// is evaluated to
319// double(int, char*);
320template <typename Callable>
321using ExtractCallableRunType =
322 typename ExtractCallableRunTypeImpl<Callable>::Type;
323
tzikf98654b2017-12-02 03:28:58324// IsCallableObject<Functor> is std::true_type if |Functor| has operator().
325// Otherwise, it's std::false_type.
tzikc1db72652016-07-08 09:42:38326// Example:
tzikf98654b2017-12-02 03:28:58327// IsCallableObject<void(*)()>::value is false.
tzikc1db72652016-07-08 09:42:38328//
329// struct Foo {};
tzikf98654b2017-12-02 03:28:58330// IsCallableObject<void(Foo::*)()>::value is false.
tzikc1db72652016-07-08 09:42:38331//
332// int i = 0;
tzikf98654b2017-12-02 03:28:58333// auto f = [i]() {};
334// IsCallableObject<decltype(f)>::value is false.
tzikc1db72652016-07-08 09:42:38335template <typename Functor, typename SFINAE = void>
tzikf98654b2017-12-02 03:28:58336struct IsCallableObject : std::false_type {};
tzikc1db72652016-07-08 09:42:38337
338template <typename Callable>
tzikf98654b2017-12-02 03:28:58339struct IsCallableObject<Callable, void_t<decltype(&Callable::operator())>>
340 : std::true_type {};
tzikc1db72652016-07-08 09:42:38341
tzik401dd3672014-11-26 07:54:58342// HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw
343// pointer to a RefCounted type.
344// Implementation note: This non-specialized case handles zero-arity case only.
345// Non-zero-arity cases should be handled by the specialization below.
346template <typename... Args>
tzik403cb6c2016-03-10 07:17:25347struct HasRefCountedTypeAsRawPtr : std::false_type {};
tzik401dd3672014-11-26 07:54:58348
349// Implementation note: Select true_type if the first parameter is a raw pointer
350// to a RefCounted type. Otherwise, skip the first parameter and check rest of
351// parameters recursively.
352template <typename T, typename... Args>
353struct HasRefCountedTypeAsRawPtr<T, Args...>
Jeremy Roman35a317432017-08-16 22:20:53354 : std::conditional_t<NeedsScopedRefptrButGetsRawPtr<T>::value,
355 std::true_type,
356 HasRefCountedTypeAsRawPtr<Args...>> {};
tzik401dd3672014-11-26 07:54:58357
[email protected]7296f2762011-11-21 19:23:44358// ForceVoidReturn<>
359//
360// Set of templates that support forcing the function return type to void.
361template <typename Sig>
362struct ForceVoidReturn;
363
tzikc82149922014-11-20 10:09:45364template <typename R, typename... Args>
365struct ForceVoidReturn<R(Args...)> {
tzik99de02b2016-07-01 05:54:12366 using RunType = void(Args...);
[email protected]fccef1552011-11-28 22:13:54367};
368
[email protected]7296f2762011-11-21 19:23:44369// FunctorTraits<>
370//
371// See description at top of file.
tzik6c92eab2016-11-25 15:56:36372template <typename Functor, typename SFINAE>
tzik99de02b2016-07-01 05:54:12373struct FunctorTraits;
374
tzikf98654b2017-12-02 03:28:58375// For empty callable types.
tzikc1db72652016-07-08 09:42:38376// This specialization is intended to allow binding captureless lambdas by
tzikf98654b2017-12-02 03:28:58377// base::Bind(), based on the fact that captureless lambdas are empty while
378// capturing lambdas are not. This also allows any functors as far as it's an
379// empty class.
380// Example:
381//
382// // Captureless lambdas are allowed.
383// []() {return 42;};
384//
385// // Capturing lambdas are *not* allowed.
386// int x;
387// [x]() {return x;};
388//
389// // Any empty class with operator() is allowed.
390// struct Foo {
391// void operator()() const {}
392// // No non-static member variable and no virtual functions.
393// };
tzikc1db72652016-07-08 09:42:38394template <typename Functor>
Jeremy Roman35a317432017-08-16 22:20:53395struct FunctorTraits<Functor,
tzikf98654b2017-12-02 03:28:58396 std::enable_if_t<IsCallableObject<Functor>::value &&
397 std::is_empty<Functor>::value>> {
tzikc1db72652016-07-08 09:42:38398 using RunType = ExtractCallableRunType<Functor>;
399 static constexpr bool is_method = false;
400 static constexpr bool is_nullable = false;
401
tzikf98654b2017-12-02 03:28:58402 template <typename RunFunctor, typename... RunArgs>
403 static ExtractReturnType<RunType> Invoke(RunFunctor&& functor,
404 RunArgs&&... args) {
405 return std::forward<RunFunctor>(functor)(std::forward<RunArgs>(args)...);
tzikc1db72652016-07-08 09:42:38406 }
407};
408
tzik99de02b2016-07-01 05:54:12409// For functions.
410template <typename R, typename... Args>
411struct FunctorTraits<R (*)(Args...)> {
412 using RunType = R(Args...);
413 static constexpr bool is_method = false;
tzikc1db72652016-07-08 09:42:38414 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12415
tzikd58a89232018-04-26 04:29:53416 template <typename Function, typename... RunArgs>
417 static R Invoke(Function&& function, RunArgs&&... args) {
418 return std::forward<Function>(function)(std::forward<RunArgs>(args)...);
tzik99de02b2016-07-01 05:54:12419 }
[email protected]7296f2762011-11-21 19:23:44420};
421
Gaurav Dholf6e3f592018-10-29 17:22:41422#if defined(OS_WIN) && !defined(ARCH_CPU_64_BITS)
tzik99de02b2016-07-01 05:54:12423
424// For functions.
425template <typename R, typename... Args>
426struct FunctorTraits<R(__stdcall*)(Args...)> {
427 using RunType = R(Args...);
428 static constexpr bool is_method = false;
tzikc1db72652016-07-08 09:42:38429 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12430
431 template <typename... RunArgs>
432 static R Invoke(R(__stdcall* function)(Args...), RunArgs&&... args) {
433 return function(std::forward<RunArgs>(args)...);
434 }
435};
436
437// For functions.
438template <typename R, typename... Args>
439struct FunctorTraits<R(__fastcall*)(Args...)> {
440 using RunType = R(Args...);
441 static constexpr bool is_method = false;
tzikc1db72652016-07-08 09:42:38442 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12443
444 template <typename... RunArgs>
445 static R Invoke(R(__fastcall* function)(Args...), RunArgs&&... args) {
446 return function(std::forward<RunArgs>(args)...);
447 }
448};
449
Gaurav Dholf6e3f592018-10-29 17:22:41450#endif // defined(OS_WIN) && !defined(ARCH_CPU_64_BITS)
tzik99de02b2016-07-01 05:54:12451
Sylvain Defresneec3270c2018-05-31 17:19:15452#if defined(OS_MACOSX)
453
454// Support for Objective-C blocks. There are two implementation depending
455// on whether Automated Reference Counting (ARC) is enabled. When ARC is
456// enabled, then the block itself can be bound as the compiler will ensure
457// its lifetime will be correctly managed. Otherwise, require the block to
458// be wrapped in a base::mac::ScopedBlock (via base::RetainBlock) that will
459// correctly manage the block lifetime.
460//
461// The two implementation ensure that the One Definition Rule (ODR) is not
462// broken (it is not possible to write a template base::RetainBlock that would
463// work correctly both with ARC enabled and disabled).
464
465#if HAS_FEATURE(objc_arc)
466
467template <typename R, typename... Args>
468struct FunctorTraits<R (^)(Args...)> {
469 using RunType = R(Args...);
470 static constexpr bool is_method = false;
471 static constexpr bool is_nullable = true;
472
473 template <typename BlockType, typename... RunArgs>
474 static R Invoke(BlockType&& block, RunArgs&&... args) {
475 // According to LLVM documentation (§ 6.3), "local variables of automatic
476 // storage duration do not have precise lifetime." Use objc_precise_lifetime
477 // to ensure that the Objective-C block is not deallocated until it has
478 // finished executing even if the Callback<> is destroyed during the block
479 // execution.
480 // https://clang.llvm.org/docs/AutomaticReferenceCounting.html#precise-lifetime-semantics
481 __attribute__((objc_precise_lifetime)) R (^scoped_block)(Args...) = block;
482 return scoped_block(std::forward<RunArgs>(args)...);
483 }
484};
485
486#else // HAS_FEATURE(objc_arc)
487
488template <typename R, typename... Args>
489struct FunctorTraits<base::mac::ScopedBlock<R (^)(Args...)>> {
490 using RunType = R(Args...);
491 static constexpr bool is_method = false;
492 static constexpr bool is_nullable = true;
493
494 template <typename BlockType, typename... RunArgs>
495 static R Invoke(BlockType&& block, RunArgs&&... args) {
496 // Copy the block to ensure that the Objective-C block is not deallocated
497 // until it has finished executing even if the Callback<> is destroyed
498 // during the block execution.
499 base::mac::ScopedBlock<R (^)(Args...)> scoped_block(block);
500 return scoped_block.get()(std::forward<RunArgs>(args)...);
501 }
502};
503
504#endif // HAS_FEATURE(objc_arc)
505#endif // defined(OS_MACOSX)
506
tzik99de02b2016-07-01 05:54:12507// For methods.
508template <typename R, typename Receiver, typename... Args>
509struct FunctorTraits<R (Receiver::*)(Args...)> {
510 using RunType = R(Receiver*, Args...);
511 static constexpr bool is_method = true;
tzikc1db72652016-07-08 09:42:38512 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12513
tzikd58a89232018-04-26 04:29:53514 template <typename Method, typename ReceiverPtr, typename... RunArgs>
515 static R Invoke(Method method,
tzik99de02b2016-07-01 05:54:12516 ReceiverPtr&& receiver_ptr,
517 RunArgs&&... args) {
tzik75851f42017-06-14 06:57:01518 return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
tzik99de02b2016-07-01 05:54:12519 }
520};
521
522// For const methods.
523template <typename R, typename Receiver, typename... Args>
524struct FunctorTraits<R (Receiver::*)(Args...) const> {
525 using RunType = R(const Receiver*, Args...);
526 static constexpr bool is_method = true;
tzikc1db72652016-07-08 09:42:38527 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12528
tzikd58a89232018-04-26 04:29:53529 template <typename Method, typename ReceiverPtr, typename... RunArgs>
530 static R Invoke(Method method,
tzik99de02b2016-07-01 05:54:12531 ReceiverPtr&& receiver_ptr,
532 RunArgs&&... args) {
tzik75851f42017-06-14 06:57:01533 return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
tzik99de02b2016-07-01 05:54:12534 }
535};
536
tzikd58a89232018-04-26 04:29:53537#ifdef __cpp_noexcept_function_type
538// noexcept makes a distinct function type in C++17.
539// I.e. `void(*)()` and `void(*)() noexcept` are same in pre-C++17, and
540// different in C++17.
541template <typename R, typename... Args>
542struct FunctorTraits<R (*)(Args...) noexcept> : FunctorTraits<R (*)(Args...)> {
543};
544
545template <typename R, typename Receiver, typename... Args>
546struct FunctorTraits<R (Receiver::*)(Args...) noexcept>
547 : FunctorTraits<R (Receiver::*)(Args...)> {};
548
549template <typename R, typename Receiver, typename... Args>
550struct FunctorTraits<R (Receiver::*)(Args...) const noexcept>
551 : FunctorTraits<R (Receiver::*)(Args...) const> {};
552#endif
553
tzik99de02b2016-07-01 05:54:12554// For IgnoreResults.
[email protected]7296f2762011-11-21 19:23:44555template <typename T>
tzik99de02b2016-07-01 05:54:12556struct FunctorTraits<IgnoreResultHelper<T>> : FunctorTraits<T> {
tzik3bc7779b2015-12-19 09:18:46557 using RunType =
tzik99de02b2016-07-01 05:54:12558 typename ForceVoidReturn<typename FunctorTraits<T>::RunType>::RunType;
559
560 template <typename IgnoreResultType, typename... RunArgs>
561 static void Invoke(IgnoreResultType&& ignore_result_helper,
562 RunArgs&&... args) {
tzikff54a5b152016-08-31 11:50:41563 FunctorTraits<T>::Invoke(
564 std::forward<IgnoreResultType>(ignore_result_helper).functor_,
565 std::forward<RunArgs>(args)...);
tzik99de02b2016-07-01 05:54:12566 }
[email protected]7296f2762011-11-21 19:23:44567};
568
tzikd4bb5b7d2017-08-28 19:08:52569// For OnceCallbacks.
570template <typename R, typename... Args>
571struct FunctorTraits<OnceCallback<R(Args...)>> {
572 using RunType = R(Args...);
573 static constexpr bool is_method = false;
574 static constexpr bool is_nullable = true;
575
576 template <typename CallbackType, typename... RunArgs>
577 static R Invoke(CallbackType&& callback, RunArgs&&... args) {
578 DCHECK(!callback.is_null());
579 return std::forward<CallbackType>(callback).Run(
580 std::forward<RunArgs>(args)...);
581 }
582};
583
584// For RepeatingCallbacks.
585template <typename R, typename... Args>
586struct FunctorTraits<RepeatingCallback<R(Args...)>> {
tzik99de02b2016-07-01 05:54:12587 using RunType = R(Args...);
588 static constexpr bool is_method = false;
tzikc1db72652016-07-08 09:42:38589 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12590
591 template <typename CallbackType, typename... RunArgs>
592 static R Invoke(CallbackType&& callback, RunArgs&&... args) {
593 DCHECK(!callback.is_null());
594 return std::forward<CallbackType>(callback).Run(
595 std::forward<RunArgs>(args)...);
596 }
[email protected]7296f2762011-11-21 19:23:44597};
598
tzikae4202e2017-07-31 10:41:54599template <typename Functor>
Jeremy Roman35a317432017-08-16 22:20:53600using MakeFunctorTraits = FunctorTraits<std::decay_t<Functor>>;
tzikae4202e2017-07-31 10:41:54601
[email protected]7296f2762011-11-21 19:23:44602// InvokeHelper<>
603//
tzik99de02b2016-07-01 05:54:12604// There are 2 logical InvokeHelper<> specializations: normal, WeakCalls.
[email protected]7296f2762011-11-21 19:23:44605//
606// The normal type just calls the underlying runnable.
607//
tzik99de02b2016-07-01 05:54:12608// WeakCalls need special syntax that is applied to the first argument to check
609// if they should no-op themselves.
tzikee248722016-06-01 08:22:51610template <bool is_weak_call, typename ReturnType>
[email protected]7296f2762011-11-21 19:23:44611struct InvokeHelper;
612
tzikee248722016-06-01 08:22:51613template <typename ReturnType>
614struct InvokeHelper<false, ReturnType> {
tzik99de02b2016-07-01 05:54:12615 template <typename Functor, typename... RunArgs>
616 static inline ReturnType MakeItSo(Functor&& functor, RunArgs&&... args) {
tzikae4202e2017-07-31 10:41:54617 using Traits = MakeFunctorTraits<Functor>;
tzik99de02b2016-07-01 05:54:12618 return Traits::Invoke(std::forward<Functor>(functor),
619 std::forward<RunArgs>(args)...);
[email protected]7296f2762011-11-21 19:23:44620 }
621};
622
tzikee248722016-06-01 08:22:51623template <typename ReturnType>
624struct InvokeHelper<true, ReturnType> {
[email protected]7296f2762011-11-21 19:23:44625 // WeakCalls are only supported for functions with a void return type.
626 // Otherwise, the function result would be undefined if the the WeakPtr<>
627 // is invalidated.
tzik403cb6c2016-03-10 07:17:25628 static_assert(std::is_void<ReturnType>::value,
avi4ec0dff2015-11-24 14:26:24629 "weak_ptrs can only bind to methods without return values");
[email protected]c18b1052011-03-24 02:02:17630
tzik99de02b2016-07-01 05:54:12631 template <typename Functor, typename BoundWeakPtr, typename... RunArgs>
632 static inline void MakeItSo(Functor&& functor,
tzik33871d82016-07-14 12:12:06633 BoundWeakPtr&& weak_ptr,
tzik99de02b2016-07-01 05:54:12634 RunArgs&&... args) {
635 if (!weak_ptr)
636 return;
tzikae4202e2017-07-31 10:41:54637 using Traits = MakeFunctorTraits<Functor>;
tzik99de02b2016-07-01 05:54:12638 Traits::Invoke(std::forward<Functor>(functor),
639 std::forward<BoundWeakPtr>(weak_ptr),
640 std::forward<RunArgs>(args)...);
641 }
642};
[email protected]b38d3572011-02-15 01:27:38643
[email protected]7296f2762011-11-21 19:23:44644// Invoker<>
645//
646// See description at the top of the file.
tzikcaf1d84b2016-06-28 12:22:21647template <typename StorageType, typename UnboundRunType>
[email protected]7296f2762011-11-21 19:23:44648struct Invoker;
649
tzikcaf1d84b2016-06-28 12:22:21650template <typename StorageType, typename R, typename... UnboundArgs>
651struct Invoker<StorageType, R(UnboundArgs...)> {
Vladislav Kuzkokov6d208e12017-11-08 21:31:08652 static R RunOnce(BindStateBase* base,
tzik9bc6837b2018-06-28 20:20:47653 PassingType<UnboundArgs>... unbound_args) {
tzik27d1e312016-09-13 05:28:59654 // Local references to make debugger stepping easier. If in a debugger,
655 // you really want to warp ahead and step through the
656 // InvokeHelper<>::MakeItSo() call below.
657 StorageType* storage = static_cast<StorageType*>(base);
658 static constexpr size_t num_bound_args =
659 std::tuple_size<decltype(storage->bound_args_)>::value;
660 return RunImpl(std::move(storage->functor_),
661 std::move(storage->bound_args_),
Jeremy Roman84956fa2017-08-16 15:55:20662 std::make_index_sequence<num_bound_args>(),
tzik27d1e312016-09-13 05:28:59663 std::forward<UnboundArgs>(unbound_args)...);
664 }
665
tzik9bc6837b2018-06-28 20:20:47666 static R Run(BindStateBase* base, PassingType<UnboundArgs>... unbound_args) {
[email protected]7296f2762011-11-21 19:23:44667 // Local references to make debugger stepping easier. If in a debugger,
668 // you really want to warp ahead and step through the
669 // InvokeHelper<>::MakeItSo() call below.
tzikcaf1d84b2016-06-28 12:22:21670 const StorageType* storage = static_cast<StorageType*>(base);
671 static constexpr size_t num_bound_args =
672 std::tuple_size<decltype(storage->bound_args_)>::value;
Jeremy Roman84956fa2017-08-16 15:55:20673 return RunImpl(storage->functor_, storage->bound_args_,
674 std::make_index_sequence<num_bound_args>(),
tzikcaf1d84b2016-06-28 12:22:21675 std::forward<UnboundArgs>(unbound_args)...);
676 }
677
tzik99de02b2016-07-01 05:54:12678 private:
679 template <typename Functor, typename BoundArgsTuple, size_t... indices>
680 static inline R RunImpl(Functor&& functor,
tzikcaf1d84b2016-06-28 12:22:21681 BoundArgsTuple&& bound,
Jeremy Roman84956fa2017-08-16 15:55:20682 std::index_sequence<indices...>,
tzikcaf1d84b2016-06-28 12:22:21683 UnboundArgs&&... unbound_args) {
tzikae4202e2017-07-31 10:41:54684 static constexpr bool is_method = MakeFunctorTraits<Functor>::is_method;
tzikcaf1d84b2016-06-28 12:22:21685
Jeremy Roman35a317432017-08-16 22:20:53686 using DecayedArgsTuple = std::decay_t<BoundArgsTuple>;
tzikcaf1d84b2016-06-28 12:22:21687 static constexpr bool is_weak_call =
688 IsWeakMethod<is_method,
Jeremy Roman35a317432017-08-16 22:20:53689 std::tuple_element_t<indices, DecayedArgsTuple>...>();
tzikcaf1d84b2016-06-28 12:22:21690
tzikee248722016-06-01 08:22:51691 return InvokeHelper<is_weak_call, R>::MakeItSo(
tzik99de02b2016-07-01 05:54:12692 std::forward<Functor>(functor),
tzikf7c47572017-04-05 21:45:03693 Unwrap(std::get<indices>(std::forward<BoundArgsTuple>(bound)))...,
tzika43eff02016-03-09 05:46:05694 std::forward<UnboundArgs>(unbound_args)...);
[email protected]fccef1552011-11-28 22:13:54695 }
696};
697
tzikae4202e2017-07-31 10:41:54698// Extracts necessary type info from Functor and BoundArgs.
699// Used to implement MakeUnboundRunType, BindOnce and BindRepeating.
tzikcaf1d84b2016-06-28 12:22:21700template <typename Functor, typename... BoundArgs>
tzikae4202e2017-07-31 10:41:54701struct BindTypeHelper {
702 static constexpr size_t num_bounds = sizeof...(BoundArgs);
703 using FunctorTraits = MakeFunctorTraits<Functor>;
704
705 // Example:
706 // When Functor is `double (Foo::*)(int, const std::string&)`, and BoundArgs
707 // is a template pack of `Foo*` and `int16_t`:
708 // - RunType is `double(Foo*, int, const std::string&)`,
709 // - ReturnType is `double`,
710 // - RunParamsList is `TypeList<Foo*, int, const std::string&>`,
711 // - BoundParamsList is `TypeList<Foo*, int>`,
712 // - UnboundParamsList is `TypeList<const std::string&>`,
713 // - BoundArgsList is `TypeList<Foo*, int16_t>`,
714 // - UnboundRunType is `double(const std::string&)`.
715 using RunType = typename FunctorTraits::RunType;
tzikcaf1d84b2016-06-28 12:22:21716 using ReturnType = ExtractReturnType<RunType>;
tzikae4202e2017-07-31 10:41:54717
718 using RunParamsList = ExtractArgs<RunType>;
719 using BoundParamsList = TakeTypeListItem<num_bounds, RunParamsList>;
720 using UnboundParamsList = DropTypeListItem<num_bounds, RunParamsList>;
721
722 using BoundArgsList = TypeList<BoundArgs...>;
723
724 using UnboundRunType = MakeFunctionType<ReturnType, UnboundParamsList>;
tzikcaf1d84b2016-06-28 12:22:21725};
tzikae4202e2017-07-31 10:41:54726
tzikc1db72652016-07-08 09:42:38727template <typename Functor>
Jeremy Roman35a317432017-08-16 22:20:53728std::enable_if_t<FunctorTraits<Functor>::is_nullable, bool> IsNull(
729 const Functor& functor) {
tzikc1db72652016-07-08 09:42:38730 return !functor;
731}
732
733template <typename Functor>
Jeremy Roman35a317432017-08-16 22:20:53734std::enable_if_t<!FunctorTraits<Functor>::is_nullable, bool> IsNull(
735 const Functor&) {
tzikc1db72652016-07-08 09:42:38736 return false;
737}
tzikcaf1d84b2016-06-28 12:22:21738
tzik9697d49e2018-08-02 13:35:19739// Used by QueryCancellationTraits below.
tzik6c92eab2016-11-25 15:56:36740template <typename Functor, typename BoundArgsTuple, size_t... indices>
tzik9697d49e2018-08-02 13:35:19741bool QueryCancellationTraitsImpl(BindStateBase::CancellationQueryMode mode,
742 const Functor& functor,
743 const BoundArgsTuple& bound_args,
744 std::index_sequence<indices...>) {
745 switch (mode) {
746 case BindStateBase::IS_CANCELLED:
747 return CallbackCancellationTraits<Functor, BoundArgsTuple>::IsCancelled(
748 functor, std::get<indices>(bound_args)...);
749 case BindStateBase::MAYBE_VALID:
750 return CallbackCancellationTraits<Functor, BoundArgsTuple>::MaybeValid(
751 functor, std::get<indices>(bound_args)...);
752 }
753 NOTREACHED();
tzik6c92eab2016-11-25 15:56:36754}
tzik59aa6bb12016-09-08 10:58:53755
tzik6c92eab2016-11-25 15:56:36756// Relays |base| to corresponding CallbackCancellationTraits<>::Run(). Returns
757// true if the callback |base| represents is canceled.
758template <typename BindStateType>
tzik9697d49e2018-08-02 13:35:19759bool QueryCancellationTraits(const BindStateBase* base,
760 BindStateBase::CancellationQueryMode mode) {
tzik6c92eab2016-11-25 15:56:36761 const BindStateType* storage = static_cast<const BindStateType*>(base);
762 static constexpr size_t num_bound_args =
763 std::tuple_size<decltype(storage->bound_args_)>::value;
tzik9697d49e2018-08-02 13:35:19764 return QueryCancellationTraitsImpl(
765 mode, storage->functor_, storage->bound_args_,
Nicolas Ouellet-payeur40f8e9a2018-07-30 16:26:48766 std::make_index_sequence<num_bound_args>());
Nicolas Ouellet-payeur40f8e9a2018-07-30 16:26:48767}
768
tzikefea4f52018-08-02 15:20:46769// The base case of BanUnconstructedRefCountedReceiver that checks nothing.
770template <typename Functor, typename Receiver, typename... Unused>
771std::enable_if_t<
772 !(MakeFunctorTraits<Functor>::is_method &&
773 std::is_pointer<std::decay_t<Receiver>>::value &&
774 IsRefCountedType<std::remove_pointer_t<std::decay_t<Receiver>>>::value)>
775BanUnconstructedRefCountedReceiver(const Receiver& receiver, Unused&&...) {}
776
777template <typename Functor>
778void BanUnconstructedRefCountedReceiver() {}
779
780// Asserts that Callback is not the first owner of a ref-counted receiver.
781template <typename Functor, typename Receiver, typename... Unused>
782std::enable_if_t<
783 MakeFunctorTraits<Functor>::is_method &&
784 std::is_pointer<std::decay_t<Receiver>>::value &&
785 IsRefCountedType<std::remove_pointer_t<std::decay_t<Receiver>>>::value>
786BanUnconstructedRefCountedReceiver(const Receiver& receiver, Unused&&...) {
787 DCHECK(receiver);
788
789 // It's error prone to make the implicit first reference to ref-counted types.
790 // In the example below, base::BindOnce() makes the implicit first reference
791 // to the ref-counted Foo. If PostTask() failed or the posted task ran fast
792 // enough, the newly created instance can be destroyed before |oo| makes
793 // another reference.
794 // Foo::Foo() {
795 // base::PostTask(FROM_HERE, base::BindOnce(&Foo::Bar, this));
796 // }
797 //
798 // scoped_refptr<Foo> oo = new Foo();
799 //
800 // Instead of doing like above, please consider adding a static constructor,
801 // and keep the first reference alive explicitly.
802 // // static
803 // scoped_refptr<Foo> Foo::Create() {
804 // auto foo = base::WrapRefCounted(new Foo());
805 // base::PostTask(FROM_HERE, base::BindOnce(&Foo::Bar, foo));
806 // return foo;
807 // }
808 //
809 // Foo::Foo() {}
810 //
811 // scoped_refptr<Foo> oo = Foo::Create();
812 DCHECK(receiver->HasAtLeastOneRef())
813 << "base::Bind() refuses to create the first reference to ref-counted "
814 "objects. That is typically happens around PostTask() in their "
815 "constructor, and such objects can be destroyed before `new` returns "
816 "if the task resolves fast enough.";
817}
818
[email protected]7296f2762011-11-21 19:23:44819// BindState<>
820//
tzik99de02b2016-07-01 05:54:12821// This stores all the state passed into Bind().
822template <typename Functor, typename... BoundArgs>
823struct BindState final : BindStateBase {
tzik1fdcca32016-09-14 07:15:00824 using IsCancellable = std::integral_constant<
tzik6c92eab2016-11-25 15:56:36825 bool,
826 CallbackCancellationTraits<Functor,
827 std::tuple<BoundArgs...>>::is_cancellable>;
tzik1fdcca32016-09-14 07:15:00828
tzikbfe66122016-07-08 14:14:01829 template <typename ForwardFunctor, typename... ForwardBoundArgs>
tzikefea4f52018-08-02 15:20:46830 static BindState* Create(BindStateBase::InvokeFuncStorage invoke_func,
831 ForwardFunctor&& functor,
832 ForwardBoundArgs&&... bound_args) {
833 // Ban ref counted receivers that were not yet fully constructed to avoid
834 // a common pattern of racy situation.
835 BanUnconstructedRefCountedReceiver<ForwardFunctor>(bound_args...);
836
837 // IsCancellable is std::false_type if
838 // CallbackCancellationTraits<>::IsCancelled returns always false.
839 // Otherwise, it's std::true_type.
840 return new BindState(IsCancellable{}, invoke_func,
841 std::forward<ForwardFunctor>(functor),
842 std::forward<ForwardBoundArgs>(bound_args)...);
843 }
tzik1fdcca32016-09-14 07:15:00844
845 Functor functor_;
846 std::tuple<BoundArgs...> bound_args_;
847
848 private:
849 template <typename ForwardFunctor, typename... ForwardBoundArgs>
850 explicit BindState(std::true_type,
851 BindStateBase::InvokeFuncStorage invoke_func,
852 ForwardFunctor&& functor,
853 ForwardBoundArgs&&... bound_args)
tzik6c92eab2016-11-25 15:56:36854 : BindStateBase(invoke_func,
855 &Destroy,
tzik9697d49e2018-08-02 13:35:19856 &QueryCancellationTraits<BindState>),
tzikff54a5b152016-08-31 11:50:41857 functor_(std::forward<ForwardFunctor>(functor)),
tzik99de02b2016-07-01 05:54:12858 bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
tzikc1db72652016-07-08 09:42:38859 DCHECK(!IsNull(functor_));
tzik99de02b2016-07-01 05:54:12860 }
[email protected]7296f2762011-11-21 19:23:44861
tzik1fdcca32016-09-14 07:15:00862 template <typename ForwardFunctor, typename... ForwardBoundArgs>
863 explicit BindState(std::false_type,
864 BindStateBase::InvokeFuncStorage invoke_func,
865 ForwardFunctor&& functor,
866 ForwardBoundArgs&&... bound_args)
867 : BindStateBase(invoke_func, &Destroy),
868 functor_(std::forward<ForwardFunctor>(functor)),
869 bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
870 DCHECK(!IsNull(functor_));
871 }
dmichael7d09007e2014-12-18 22:30:11872
Chris Watkins091d6292017-12-13 04:25:58873 ~BindState() = default;
taptede7e804c2015-05-14 08:03:32874
tzik30e0c312016-09-21 08:06:54875 static void Destroy(const BindStateBase* self) {
876 delete static_cast<const BindState*>(self);
taptede7e804c2015-05-14 08:03:32877 }
[email protected]fccef1552011-11-28 22:13:54878};
879
tzik99de02b2016-07-01 05:54:12880// Used to implement MakeBindStateType.
881template <bool is_method, typename Functor, typename... BoundArgs>
882struct MakeBindStateTypeImpl;
883
884template <typename Functor, typename... BoundArgs>
885struct MakeBindStateTypeImpl<false, Functor, BoundArgs...> {
Jeremy Roman35a317432017-08-16 22:20:53886 static_assert(!HasRefCountedTypeAsRawPtr<std::decay_t<BoundArgs>...>::value,
tzik99de02b2016-07-01 05:54:12887 "A parameter is a refcounted type and needs scoped_refptr.");
Jeremy Roman35a317432017-08-16 22:20:53888 using Type = BindState<std::decay_t<Functor>, std::decay_t<BoundArgs>...>;
tzik99de02b2016-07-01 05:54:12889};
890
891template <typename Functor>
892struct MakeBindStateTypeImpl<true, Functor> {
Jeremy Roman35a317432017-08-16 22:20:53893 using Type = BindState<std::decay_t<Functor>>;
tzik99de02b2016-07-01 05:54:12894};
895
896template <typename Functor, typename Receiver, typename... BoundArgs>
897struct MakeBindStateTypeImpl<true, Functor, Receiver, BoundArgs...> {
tzik99de02b2016-07-01 05:54:12898 private:
Jeremy Roman35a317432017-08-16 22:20:53899 using DecayedReceiver = std::decay_t<Receiver>;
tzik99de02b2016-07-01 05:54:12900
tzik4625ac612018-02-28 09:43:55901 static_assert(!std::is_array<std::remove_reference_t<Receiver>>::value,
902 "First bound argument to a method cannot be an array.");
903 static_assert(
904 !std::is_pointer<DecayedReceiver>::value ||
905 IsRefCountedType<std::remove_pointer_t<DecayedReceiver>>::value,
906 "Receivers may not be raw pointers. If using a raw pointer here is safe"
907 " and has no lifetime concerns, use base::Unretained() and document why"
908 " it's safe.");
909 static_assert(!HasRefCountedTypeAsRawPtr<std::decay_t<BoundArgs>...>::value,
910 "A parameter is a refcounted type and needs scoped_refptr.");
911
tzik99de02b2016-07-01 05:54:12912 public:
913 using Type = BindState<
Jeremy Roman35a317432017-08-16 22:20:53914 std::decay_t<Functor>,
915 std::conditional_t<std::is_pointer<DecayedReceiver>::value,
916 scoped_refptr<std::remove_pointer_t<DecayedReceiver>>,
917 DecayedReceiver>,
918 std::decay_t<BoundArgs>...>;
tzik99de02b2016-07-01 05:54:12919};
920
921template <typename Functor, typename... BoundArgs>
tzikae4202e2017-07-31 10:41:54922using MakeBindStateType =
923 typename MakeBindStateTypeImpl<MakeFunctorTraits<Functor>::is_method,
924 Functor,
925 BoundArgs...>::Type;
tzik99de02b2016-07-01 05:54:12926
[email protected]b38d3572011-02-15 01:27:38927} // namespace internal
tzikcaf1d84b2016-06-28 12:22:21928
Peter Kastinga85265e32018-02-15 08:30:23929// An injection point to control |this| pointer behavior on a method invocation.
930// If IsWeakReceiver<> is true_type for |T| and |T| is used for a receiver of a
931// method, base::Bind cancels the method invocation if the receiver is tested as
932// false.
933// E.g. Foo::bar() is not called:
934// struct Foo : base::SupportsWeakPtr<Foo> {
935// void bar() {}
936// };
937//
938// WeakPtr<Foo> oo = nullptr;
939// base::Bind(&Foo::bar, oo).Run();
940template <typename T>
941struct IsWeakReceiver : std::false_type {};
942
943template <typename T>
944struct IsWeakReceiver<internal::ConstRefWrapper<T>> : IsWeakReceiver<T> {};
945
946template <typename T>
947struct IsWeakReceiver<WeakPtr<T>> : std::true_type {};
948
949// An injection point to control how bound objects passed to the target
950// function. BindUnwrapTraits<>::Unwrap() is called for each bound objects right
951// before the target function is invoked.
952template <typename>
953struct BindUnwrapTraits {
954 template <typename T>
955 static T&& Unwrap(T&& o) {
956 return std::forward<T>(o);
957 }
958};
959
960template <typename T>
961struct BindUnwrapTraits<internal::UnretainedWrapper<T>> {
962 static T* Unwrap(const internal::UnretainedWrapper<T>& o) { return o.get(); }
963};
964
965template <typename T>
966struct BindUnwrapTraits<internal::ConstRefWrapper<T>> {
967 static const T& Unwrap(const internal::ConstRefWrapper<T>& o) {
968 return o.get();
969 }
970};
971
972template <typename T>
973struct BindUnwrapTraits<internal::RetainedRefWrapper<T>> {
974 static T* Unwrap(const internal::RetainedRefWrapper<T>& o) { return o.get(); }
975};
976
977template <typename T>
978struct BindUnwrapTraits<internal::OwnedWrapper<T>> {
979 static T* Unwrap(const internal::OwnedWrapper<T>& o) { return o.get(); }
980};
981
982template <typename T>
983struct BindUnwrapTraits<internal::PassedWrapper<T>> {
984 static T Unwrap(const internal::PassedWrapper<T>& o) { return o.Take(); }
985};
986
tzikc44f8102018-07-24 09:49:19987#if defined(OS_WIN)
988template <typename T>
989struct BindUnwrapTraits<Microsoft::WRL::ComPtr<T>> {
990 static T* Unwrap(const Microsoft::WRL::ComPtr<T>& ptr) { return ptr.Get(); }
991};
992#endif
993
Peter Kastinga85265e32018-02-15 08:30:23994// CallbackCancellationTraits allows customization of Callback's cancellation
995// semantics. By default, callbacks are not cancellable. A specialization should
996// set is_cancellable = true and implement an IsCancelled() that returns if the
997// callback should be cancelled.
998template <typename Functor, typename BoundArgsTuple, typename SFINAE>
999struct CallbackCancellationTraits {
1000 static constexpr bool is_cancellable = false;
1001};
1002
1003// Specialization for method bound to weak pointer receiver.
1004template <typename Functor, typename... BoundArgs>
1005struct CallbackCancellationTraits<
1006 Functor,
1007 std::tuple<BoundArgs...>,
1008 std::enable_if_t<
1009 internal::IsWeakMethod<internal::FunctorTraits<Functor>::is_method,
1010 BoundArgs...>::value>> {
1011 static constexpr bool is_cancellable = true;
1012
1013 template <typename Receiver, typename... Args>
1014 static bool IsCancelled(const Functor&,
1015 const Receiver& receiver,
1016 const Args&...) {
1017 return !receiver;
1018 }
Nicolas Ouellet-payeur40f8e9a2018-07-30 16:26:481019
1020 template <typename Receiver, typename... Args>
1021 static bool MaybeValid(const Functor&,
1022 const Receiver& receiver,
1023 const Args&...) {
1024 return receiver.MaybeValid();
1025 }
Peter Kastinga85265e32018-02-15 08:30:231026};
1027
1028// Specialization for a nested bind.
1029template <typename Signature, typename... BoundArgs>
1030struct CallbackCancellationTraits<OnceCallback<Signature>,
1031 std::tuple<BoundArgs...>> {
1032 static constexpr bool is_cancellable = true;
1033
1034 template <typename Functor>
1035 static bool IsCancelled(const Functor& functor, const BoundArgs&...) {
1036 return functor.IsCancelled();
1037 }
Nicolas Ouellet-payeur40f8e9a2018-07-30 16:26:481038
1039 template <typename Functor>
1040 static bool MaybeValid(const Functor& functor, const BoundArgs&...) {
1041 return functor.MaybeValid();
1042 }
Peter Kastinga85265e32018-02-15 08:30:231043};
1044
1045template <typename Signature, typename... BoundArgs>
1046struct CallbackCancellationTraits<RepeatingCallback<Signature>,
1047 std::tuple<BoundArgs...>> {
1048 static constexpr bool is_cancellable = true;
1049
1050 template <typename Functor>
1051 static bool IsCancelled(const Functor& functor, const BoundArgs&...) {
1052 return functor.IsCancelled();
1053 }
Nicolas Ouellet-payeur40f8e9a2018-07-30 16:26:481054
1055 template <typename Functor>
1056 static bool MaybeValid(const Functor& functor, const BoundArgs&...) {
1057 return functor.MaybeValid();
1058 }
Peter Kastinga85265e32018-02-15 08:30:231059};
1060
tzikcaf1d84b2016-06-28 12:22:211061// Returns a RunType of bound functor.
1062// E.g. MakeUnboundRunType<R(A, B, C), A, B> is evaluated to R(C).
1063template <typename Functor, typename... BoundArgs>
1064using MakeUnboundRunType =
tzikae4202e2017-07-31 10:41:541065 typename internal::BindTypeHelper<Functor, BoundArgs...>::UnboundRunType;
tzikcaf1d84b2016-06-28 12:22:211066
[email protected]b38d3572011-02-15 01:27:381067} // namespace base
1068
1069#endif // BASE_BIND_INTERNAL_H_