blob: 9d3a8026927d3d5a5e72d2d8d924f4391bebaff8 [file] [log] [blame]
[email protected]b38d3572011-02-15 01:27:381// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef BASE_BIND_INTERNAL_H_
6#define BASE_BIND_INTERNAL_H_
[email protected]b38d3572011-02-15 01:27:387
avi9b6f42932015-12-26 22:15:148#include <stddef.h>
9
vmpstrc52317f2015-11-18 08:43:2610#include <type_traits>
Jeremy Roman84956fa2017-08-16 15:55:2011#include <utility>
vmpstrc52317f2015-11-18 08:43:2612
[email protected]59eff912011-02-18 23:29:3113#include "base/callback_internal.h"
[email protected]8217d4542011-10-01 06:31:4114#include "base/memory/raw_scoped_refptr_mismatch_checker.h"
[email protected]93540582011-05-16 22:35:1415#include "base/memory/weak_ptr.h"
[email protected]b38d3572011-02-15 01:27:3816#include "base/template_util.h"
[email protected]054ac7542011-02-27 01:25:5917#include "build/build_config.h"
18
[email protected]24292642012-07-12 20:06:4019// See base/callback.h for user documentation.
20//
21//
[email protected]7296f2762011-11-21 19:23:4422// CONCEPTS:
tzik99de02b2016-07-01 05:54:1223// Functor -- A movable type representing something that should be called.
24// All function pointers and Callback<> are functors even if the
25// invocation syntax differs.
[email protected]7296f2762011-11-21 19:23:4426// RunType -- A function type (as opposed to function _pointer_ type) for
tzik99de02b2016-07-01 05:54:1227// a Callback<>::Run(). Usually just a convenience typedef.
tzikce3ecf82015-12-15 06:41:4928// (Bound)Args -- A set of types that stores the arguments.
[email protected]b38d3572011-02-15 01:27:3829//
[email protected]7296f2762011-11-21 19:23:4430// Types:
[email protected]7296f2762011-11-21 19:23:4431// ForceVoidReturn<> -- Helper class for translating function signatures to
32// equivalent forms with a "void" return type.
tzik99de02b2016-07-01 05:54:1233// FunctorTraits<> -- Type traits used to determine the correct RunType and
34// invocation manner for a Functor. This is where function
[email protected]7296f2762011-11-21 19:23:4435// signature adapters are applied.
tzik99de02b2016-07-01 05:54:1236// InvokeHelper<> -- Take a Functor + arguments and actully invokes it.
tzik8ce65702015-02-05 19:11:2637// Handle the differing syntaxes needed for WeakPtr<>
tzik99de02b2016-07-01 05:54:1238// support. This is separate from Invoker to avoid creating
39// multiple version of Invoker<>.
40// Invoker<> -- Unwraps the curried parameters and executes the Functor.
[email protected]7296f2762011-11-21 19:23:4441// BindState<> -- Stores the curried parameters, and is the main entry point
tzik99de02b2016-07-01 05:54:1242// into the Bind() system.
[email protected]4346ef912011-02-19 00:52:1543
Peter Kastinga85265e32018-02-15 08:30:2344namespace base {
45
46template <typename T>
47struct IsWeakReceiver;
48
49template <typename>
50struct BindUnwrapTraits;
51
52template <typename Functor, typename BoundArgsTuple, typename SFINAE = void>
53struct CallbackCancellationTraits;
54
55namespace internal {
56
57template <typename Functor, typename SFINAE = void>
58struct FunctorTraits;
59
60template <typename T>
61class UnretainedWrapper {
62 public:
63 explicit UnretainedWrapper(T* o) : ptr_(o) {}
64 T* get() const { return ptr_; }
65
66 private:
67 T* ptr_;
68};
69
70template <typename T>
71class ConstRefWrapper {
72 public:
73 explicit ConstRefWrapper(const T& o) : ptr_(&o) {}
74 const T& get() const { return *ptr_; }
75
76 private:
77 const T* ptr_;
78};
79
80template <typename T>
81class RetainedRefWrapper {
82 public:
83 explicit RetainedRefWrapper(T* o) : ptr_(o) {}
84 explicit RetainedRefWrapper(scoped_refptr<T> o) : ptr_(std::move(o)) {}
85 T* get() const { return ptr_.get(); }
86
87 private:
88 scoped_refptr<T> ptr_;
89};
90
91template <typename T>
92struct IgnoreResultHelper {
93 explicit IgnoreResultHelper(T functor) : functor_(std::move(functor)) {}
94 explicit operator bool() const { return !!functor_; }
95
96 T functor_;
97};
98
99// An alternate implementation is to avoid the destructive copy, and instead
100// specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to
101// a class that is essentially a std::unique_ptr<>.
102//
103// The current implementation has the benefit though of leaving ParamTraits<>
104// fully in callback_internal.h as well as avoiding type conversions during
105// storage.
106template <typename T>
107class OwnedWrapper {
108 public:
109 explicit OwnedWrapper(T* o) : ptr_(o) {}
110 ~OwnedWrapper() { delete ptr_; }
111 T* get() const { return ptr_; }
112 OwnedWrapper(OwnedWrapper&& other) {
113 ptr_ = other.ptr_;
114 other.ptr_ = NULL;
115 }
116
117 private:
118 mutable T* ptr_;
119};
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>
166auto Unwrap(T&& o) -> decltype(Unwrapper<T>::Unwrap(std::forward<T>(o))) {
167 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
tzik401dd3672014-11-26 07:54:58326// HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw
327// pointer to a RefCounted type.
328// Implementation note: This non-specialized case handles zero-arity case only.
329// Non-zero-arity cases should be handled by the specialization below.
330template <typename... Args>
tzik403cb6c2016-03-10 07:17:25331struct HasRefCountedTypeAsRawPtr : std::false_type {};
tzik401dd3672014-11-26 07:54:58332
333// Implementation note: Select true_type if the first parameter is a raw pointer
334// to a RefCounted type. Otherwise, skip the first parameter and check rest of
335// parameters recursively.
336template <typename T, typename... Args>
337struct HasRefCountedTypeAsRawPtr<T, Args...>
Jeremy Roman35a317432017-08-16 22:20:53338 : std::conditional_t<NeedsScopedRefptrButGetsRawPtr<T>::value,
339 std::true_type,
340 HasRefCountedTypeAsRawPtr<Args...>> {};
tzik401dd3672014-11-26 07:54:58341
[email protected]7296f2762011-11-21 19:23:44342// ForceVoidReturn<>
343//
344// Set of templates that support forcing the function return type to void.
345template <typename Sig>
346struct ForceVoidReturn;
347
tzikc82149922014-11-20 10:09:45348template <typename R, typename... Args>
349struct ForceVoidReturn<R(Args...)> {
tzik99de02b2016-07-01 05:54:12350 using RunType = void(Args...);
[email protected]fccef1552011-11-28 22:13:54351};
352
[email protected]7296f2762011-11-21 19:23:44353// FunctorTraits<>
354//
355// See description at top of file.
tzik6c92eab2016-11-25 15:56:36356template <typename Functor, typename SFINAE>
tzik99de02b2016-07-01 05:54:12357struct FunctorTraits;
358
tzikf98654b2017-12-02 03:28:58359// For empty callable types.
tzikc1db72652016-07-08 09:42:38360// This specialization is intended to allow binding captureless lambdas by
tzikf98654b2017-12-02 03:28:58361// base::Bind(), based on the fact that captureless lambdas are empty while
362// capturing lambdas are not. This also allows any functors as far as it's an
363// empty class.
364// Example:
365//
366// // Captureless lambdas are allowed.
367// []() {return 42;};
368//
369// // Capturing lambdas are *not* allowed.
370// int x;
371// [x]() {return x;};
372//
373// // Any empty class with operator() is allowed.
374// struct Foo {
375// void operator()() const {}
376// // No non-static member variable and no virtual functions.
377// };
tzikc1db72652016-07-08 09:42:38378template <typename Functor>
Jeremy Roman35a317432017-08-16 22:20:53379struct FunctorTraits<Functor,
tzikf98654b2017-12-02 03:28:58380 std::enable_if_t<IsCallableObject<Functor>::value &&
381 std::is_empty<Functor>::value>> {
tzikc1db72652016-07-08 09:42:38382 using RunType = ExtractCallableRunType<Functor>;
383 static constexpr bool is_method = false;
384 static constexpr bool is_nullable = false;
385
tzikf98654b2017-12-02 03:28:58386 template <typename RunFunctor, typename... RunArgs>
387 static ExtractReturnType<RunType> Invoke(RunFunctor&& functor,
388 RunArgs&&... args) {
389 return std::forward<RunFunctor>(functor)(std::forward<RunArgs>(args)...);
tzikc1db72652016-07-08 09:42:38390 }
391};
392
tzik99de02b2016-07-01 05:54:12393// For functions.
394template <typename R, typename... Args>
395struct FunctorTraits<R (*)(Args...)> {
396 using RunType = R(Args...);
397 static constexpr bool is_method = false;
tzikc1db72652016-07-08 09:42:38398 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12399
400 template <typename... RunArgs>
401 static R Invoke(R (*function)(Args...), RunArgs&&... args) {
402 return function(std::forward<RunArgs>(args)...);
403 }
[email protected]7296f2762011-11-21 19:23:44404};
405
tzik99de02b2016-07-01 05:54:12406#if defined(OS_WIN) && !defined(ARCH_CPU_X86_64)
407
408// For functions.
409template <typename R, typename... Args>
410struct FunctorTraits<R(__stdcall*)(Args...)> {
411 using RunType = R(Args...);
412 static constexpr bool is_method = false;
tzikc1db72652016-07-08 09:42:38413 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12414
415 template <typename... RunArgs>
416 static R Invoke(R(__stdcall* function)(Args...), RunArgs&&... args) {
417 return function(std::forward<RunArgs>(args)...);
418 }
419};
420
421// For functions.
422template <typename R, typename... Args>
423struct FunctorTraits<R(__fastcall*)(Args...)> {
424 using RunType = R(Args...);
425 static constexpr bool is_method = false;
tzikc1db72652016-07-08 09:42:38426 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12427
428 template <typename... RunArgs>
429 static R Invoke(R(__fastcall* function)(Args...), RunArgs&&... args) {
430 return function(std::forward<RunArgs>(args)...);
431 }
432};
433
434#endif // defined(OS_WIN) && !defined(ARCH_CPU_X86_64)
435
436// For methods.
437template <typename R, typename Receiver, typename... Args>
438struct FunctorTraits<R (Receiver::*)(Args...)> {
439 using RunType = R(Receiver*, Args...);
440 static constexpr bool is_method = true;
tzikc1db72652016-07-08 09:42:38441 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12442
443 template <typename ReceiverPtr, typename... RunArgs>
444 static R Invoke(R (Receiver::*method)(Args...),
445 ReceiverPtr&& receiver_ptr,
446 RunArgs&&... args) {
tzik75851f42017-06-14 06:57:01447 return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
tzik99de02b2016-07-01 05:54:12448 }
449};
450
451// For const methods.
452template <typename R, typename Receiver, typename... Args>
453struct FunctorTraits<R (Receiver::*)(Args...) const> {
454 using RunType = R(const Receiver*, Args...);
455 static constexpr bool is_method = true;
tzikc1db72652016-07-08 09:42:38456 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12457
458 template <typename ReceiverPtr, typename... RunArgs>
459 static R Invoke(R (Receiver::*method)(Args...) const,
460 ReceiverPtr&& receiver_ptr,
461 RunArgs&&... args) {
tzik75851f42017-06-14 06:57:01462 return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
tzik99de02b2016-07-01 05:54:12463 }
464};
465
466// For IgnoreResults.
[email protected]7296f2762011-11-21 19:23:44467template <typename T>
tzik99de02b2016-07-01 05:54:12468struct FunctorTraits<IgnoreResultHelper<T>> : FunctorTraits<T> {
tzik3bc7779b2015-12-19 09:18:46469 using RunType =
tzik99de02b2016-07-01 05:54:12470 typename ForceVoidReturn<typename FunctorTraits<T>::RunType>::RunType;
471
472 template <typename IgnoreResultType, typename... RunArgs>
473 static void Invoke(IgnoreResultType&& ignore_result_helper,
474 RunArgs&&... args) {
tzikff54a5b152016-08-31 11:50:41475 FunctorTraits<T>::Invoke(
476 std::forward<IgnoreResultType>(ignore_result_helper).functor_,
477 std::forward<RunArgs>(args)...);
tzik99de02b2016-07-01 05:54:12478 }
[email protected]7296f2762011-11-21 19:23:44479};
480
tzikd4bb5b7d2017-08-28 19:08:52481// For OnceCallbacks.
482template <typename R, typename... Args>
483struct FunctorTraits<OnceCallback<R(Args...)>> {
484 using RunType = R(Args...);
485 static constexpr bool is_method = false;
486 static constexpr bool is_nullable = true;
487
488 template <typename CallbackType, typename... RunArgs>
489 static R Invoke(CallbackType&& callback, RunArgs&&... args) {
490 DCHECK(!callback.is_null());
491 return std::forward<CallbackType>(callback).Run(
492 std::forward<RunArgs>(args)...);
493 }
494};
495
496// For RepeatingCallbacks.
497template <typename R, typename... Args>
498struct FunctorTraits<RepeatingCallback<R(Args...)>> {
tzik99de02b2016-07-01 05:54:12499 using RunType = R(Args...);
500 static constexpr bool is_method = false;
tzikc1db72652016-07-08 09:42:38501 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12502
503 template <typename CallbackType, typename... RunArgs>
504 static R Invoke(CallbackType&& callback, RunArgs&&... args) {
505 DCHECK(!callback.is_null());
506 return std::forward<CallbackType>(callback).Run(
507 std::forward<RunArgs>(args)...);
508 }
[email protected]7296f2762011-11-21 19:23:44509};
510
tzikae4202e2017-07-31 10:41:54511template <typename Functor>
Jeremy Roman35a317432017-08-16 22:20:53512using MakeFunctorTraits = FunctorTraits<std::decay_t<Functor>>;
tzikae4202e2017-07-31 10:41:54513
[email protected]7296f2762011-11-21 19:23:44514// InvokeHelper<>
515//
tzik99de02b2016-07-01 05:54:12516// There are 2 logical InvokeHelper<> specializations: normal, WeakCalls.
[email protected]7296f2762011-11-21 19:23:44517//
518// The normal type just calls the underlying runnable.
519//
tzik99de02b2016-07-01 05:54:12520// WeakCalls need special syntax that is applied to the first argument to check
521// if they should no-op themselves.
tzikee248722016-06-01 08:22:51522template <bool is_weak_call, typename ReturnType>
[email protected]7296f2762011-11-21 19:23:44523struct InvokeHelper;
524
tzikee248722016-06-01 08:22:51525template <typename ReturnType>
526struct InvokeHelper<false, ReturnType> {
tzik99de02b2016-07-01 05:54:12527 template <typename Functor, typename... RunArgs>
528 static inline ReturnType MakeItSo(Functor&& functor, RunArgs&&... args) {
tzikae4202e2017-07-31 10:41:54529 using Traits = MakeFunctorTraits<Functor>;
tzik99de02b2016-07-01 05:54:12530 return Traits::Invoke(std::forward<Functor>(functor),
531 std::forward<RunArgs>(args)...);
[email protected]7296f2762011-11-21 19:23:44532 }
533};
534
tzikee248722016-06-01 08:22:51535template <typename ReturnType>
536struct InvokeHelper<true, ReturnType> {
[email protected]7296f2762011-11-21 19:23:44537 // WeakCalls are only supported for functions with a void return type.
538 // Otherwise, the function result would be undefined if the the WeakPtr<>
539 // is invalidated.
tzik403cb6c2016-03-10 07:17:25540 static_assert(std::is_void<ReturnType>::value,
avi4ec0dff2015-11-24 14:26:24541 "weak_ptrs can only bind to methods without return values");
[email protected]c18b1052011-03-24 02:02:17542
tzik99de02b2016-07-01 05:54:12543 template <typename Functor, typename BoundWeakPtr, typename... RunArgs>
544 static inline void MakeItSo(Functor&& functor,
tzik33871d82016-07-14 12:12:06545 BoundWeakPtr&& weak_ptr,
tzik99de02b2016-07-01 05:54:12546 RunArgs&&... args) {
547 if (!weak_ptr)
548 return;
tzikae4202e2017-07-31 10:41:54549 using Traits = MakeFunctorTraits<Functor>;
tzik99de02b2016-07-01 05:54:12550 Traits::Invoke(std::forward<Functor>(functor),
551 std::forward<BoundWeakPtr>(weak_ptr),
552 std::forward<RunArgs>(args)...);
553 }
554};
[email protected]b38d3572011-02-15 01:27:38555
[email protected]7296f2762011-11-21 19:23:44556// Invoker<>
557//
558// See description at the top of the file.
tzikcaf1d84b2016-06-28 12:22:21559template <typename StorageType, typename UnboundRunType>
[email protected]7296f2762011-11-21 19:23:44560struct Invoker;
561
tzikcaf1d84b2016-06-28 12:22:21562template <typename StorageType, typename R, typename... UnboundArgs>
563struct Invoker<StorageType, R(UnboundArgs...)> {
Vladislav Kuzkokov6d208e12017-11-08 21:31:08564 static R RunOnce(BindStateBase* base,
565 PassingTraitsType<UnboundArgs>... unbound_args) {
tzik27d1e312016-09-13 05:28:59566 // Local references to make debugger stepping easier. If in a debugger,
567 // you really want to warp ahead and step through the
568 // InvokeHelper<>::MakeItSo() call below.
569 StorageType* storage = static_cast<StorageType*>(base);
570 static constexpr size_t num_bound_args =
571 std::tuple_size<decltype(storage->bound_args_)>::value;
572 return RunImpl(std::move(storage->functor_),
573 std::move(storage->bound_args_),
Jeremy Roman84956fa2017-08-16 15:55:20574 std::make_index_sequence<num_bound_args>(),
tzik27d1e312016-09-13 05:28:59575 std::forward<UnboundArgs>(unbound_args)...);
576 }
577
Vladislav Kuzkokov6d208e12017-11-08 21:31:08578 static R Run(BindStateBase* base,
579 PassingTraitsType<UnboundArgs>... unbound_args) {
[email protected]7296f2762011-11-21 19:23:44580 // Local references to make debugger stepping easier. If in a debugger,
581 // you really want to warp ahead and step through the
582 // InvokeHelper<>::MakeItSo() call below.
tzikcaf1d84b2016-06-28 12:22:21583 const StorageType* storage = static_cast<StorageType*>(base);
584 static constexpr size_t num_bound_args =
585 std::tuple_size<decltype(storage->bound_args_)>::value;
Jeremy Roman84956fa2017-08-16 15:55:20586 return RunImpl(storage->functor_, storage->bound_args_,
587 std::make_index_sequence<num_bound_args>(),
tzikcaf1d84b2016-06-28 12:22:21588 std::forward<UnboundArgs>(unbound_args)...);
589 }
590
tzik99de02b2016-07-01 05:54:12591 private:
592 template <typename Functor, typename BoundArgsTuple, size_t... indices>
593 static inline R RunImpl(Functor&& functor,
tzikcaf1d84b2016-06-28 12:22:21594 BoundArgsTuple&& bound,
Jeremy Roman84956fa2017-08-16 15:55:20595 std::index_sequence<indices...>,
tzikcaf1d84b2016-06-28 12:22:21596 UnboundArgs&&... unbound_args) {
tzikae4202e2017-07-31 10:41:54597 static constexpr bool is_method = MakeFunctorTraits<Functor>::is_method;
tzikcaf1d84b2016-06-28 12:22:21598
Jeremy Roman35a317432017-08-16 22:20:53599 using DecayedArgsTuple = std::decay_t<BoundArgsTuple>;
tzikcaf1d84b2016-06-28 12:22:21600 static constexpr bool is_weak_call =
601 IsWeakMethod<is_method,
Jeremy Roman35a317432017-08-16 22:20:53602 std::tuple_element_t<indices, DecayedArgsTuple>...>();
tzikcaf1d84b2016-06-28 12:22:21603
tzikee248722016-06-01 08:22:51604 return InvokeHelper<is_weak_call, R>::MakeItSo(
tzik99de02b2016-07-01 05:54:12605 std::forward<Functor>(functor),
tzikf7c47572017-04-05 21:45:03606 Unwrap(std::get<indices>(std::forward<BoundArgsTuple>(bound)))...,
tzika43eff02016-03-09 05:46:05607 std::forward<UnboundArgs>(unbound_args)...);
[email protected]fccef1552011-11-28 22:13:54608 }
609};
610
tzikae4202e2017-07-31 10:41:54611// Extracts necessary type info from Functor and BoundArgs.
612// Used to implement MakeUnboundRunType, BindOnce and BindRepeating.
tzikcaf1d84b2016-06-28 12:22:21613template <typename Functor, typename... BoundArgs>
tzikae4202e2017-07-31 10:41:54614struct BindTypeHelper {
615 static constexpr size_t num_bounds = sizeof...(BoundArgs);
616 using FunctorTraits = MakeFunctorTraits<Functor>;
617
618 // Example:
619 // When Functor is `double (Foo::*)(int, const std::string&)`, and BoundArgs
620 // is a template pack of `Foo*` and `int16_t`:
621 // - RunType is `double(Foo*, int, const std::string&)`,
622 // - ReturnType is `double`,
623 // - RunParamsList is `TypeList<Foo*, int, const std::string&>`,
624 // - BoundParamsList is `TypeList<Foo*, int>`,
625 // - UnboundParamsList is `TypeList<const std::string&>`,
626 // - BoundArgsList is `TypeList<Foo*, int16_t>`,
627 // - UnboundRunType is `double(const std::string&)`.
628 using RunType = typename FunctorTraits::RunType;
tzikcaf1d84b2016-06-28 12:22:21629 using ReturnType = ExtractReturnType<RunType>;
tzikae4202e2017-07-31 10:41:54630
631 using RunParamsList = ExtractArgs<RunType>;
632 using BoundParamsList = TakeTypeListItem<num_bounds, RunParamsList>;
633 using UnboundParamsList = DropTypeListItem<num_bounds, RunParamsList>;
634
635 using BoundArgsList = TypeList<BoundArgs...>;
636
637 using UnboundRunType = MakeFunctionType<ReturnType, UnboundParamsList>;
tzikcaf1d84b2016-06-28 12:22:21638};
tzikae4202e2017-07-31 10:41:54639
tzikc1db72652016-07-08 09:42:38640template <typename Functor>
Jeremy Roman35a317432017-08-16 22:20:53641std::enable_if_t<FunctorTraits<Functor>::is_nullable, bool> IsNull(
642 const Functor& functor) {
tzikc1db72652016-07-08 09:42:38643 return !functor;
644}
645
646template <typename Functor>
Jeremy Roman35a317432017-08-16 22:20:53647std::enable_if_t<!FunctorTraits<Functor>::is_nullable, bool> IsNull(
648 const Functor&) {
tzikc1db72652016-07-08 09:42:38649 return false;
650}
tzikcaf1d84b2016-06-28 12:22:21651
tzik6c92eab2016-11-25 15:56:36652// Used by ApplyCancellationTraits below.
653template <typename Functor, typename BoundArgsTuple, size_t... indices>
654bool ApplyCancellationTraitsImpl(const Functor& functor,
655 const BoundArgsTuple& bound_args,
Jeremy Roman84956fa2017-08-16 15:55:20656 std::index_sequence<indices...>) {
tzik6c92eab2016-11-25 15:56:36657 return CallbackCancellationTraits<Functor, BoundArgsTuple>::IsCancelled(
tzikf7c47572017-04-05 21:45:03658 functor, std::get<indices>(bound_args)...);
tzik6c92eab2016-11-25 15:56:36659}
tzik59aa6bb12016-09-08 10:58:53660
tzik6c92eab2016-11-25 15:56:36661// Relays |base| to corresponding CallbackCancellationTraits<>::Run(). Returns
662// true if the callback |base| represents is canceled.
663template <typename BindStateType>
664bool ApplyCancellationTraits(const BindStateBase* base) {
665 const BindStateType* storage = static_cast<const BindStateType*>(base);
666 static constexpr size_t num_bound_args =
667 std::tuple_size<decltype(storage->bound_args_)>::value;
Jeremy Roman84956fa2017-08-16 15:55:20668 return ApplyCancellationTraitsImpl(
669 storage->functor_, storage->bound_args_,
670 std::make_index_sequence<num_bound_args>());
tzik59aa6bb12016-09-08 10:58:53671};
672
[email protected]7296f2762011-11-21 19:23:44673// BindState<>
674//
tzik99de02b2016-07-01 05:54:12675// This stores all the state passed into Bind().
676template <typename Functor, typename... BoundArgs>
677struct BindState final : BindStateBase {
tzik1fdcca32016-09-14 07:15:00678 using IsCancellable = std::integral_constant<
tzik6c92eab2016-11-25 15:56:36679 bool,
680 CallbackCancellationTraits<Functor,
681 std::tuple<BoundArgs...>>::is_cancellable>;
tzik1fdcca32016-09-14 07:15:00682
tzikbfe66122016-07-08 14:14:01683 template <typename ForwardFunctor, typename... ForwardBoundArgs>
tzik1886c272016-09-08 05:45:38684 explicit BindState(BindStateBase::InvokeFuncStorage invoke_func,
685 ForwardFunctor&& functor,
686 ForwardBoundArgs&&... bound_args)
tzik6c92eab2016-11-25 15:56:36687 // IsCancellable is std::false_type if
688 // CallbackCancellationTraits<>::IsCancelled returns always false.
689 // Otherwise, it's std::true_type.
tzik1fdcca32016-09-14 07:15:00690 : BindState(IsCancellable{},
691 invoke_func,
692 std::forward<ForwardFunctor>(functor),
tzikf98654b2017-12-02 03:28:58693 std::forward<ForwardBoundArgs>(bound_args)...) {}
tzik1fdcca32016-09-14 07:15:00694
695 Functor functor_;
696 std::tuple<BoundArgs...> bound_args_;
697
698 private:
699 template <typename ForwardFunctor, typename... ForwardBoundArgs>
700 explicit BindState(std::true_type,
701 BindStateBase::InvokeFuncStorage invoke_func,
702 ForwardFunctor&& functor,
703 ForwardBoundArgs&&... bound_args)
tzik6c92eab2016-11-25 15:56:36704 : BindStateBase(invoke_func,
705 &Destroy,
706 &ApplyCancellationTraits<BindState>),
tzikff54a5b152016-08-31 11:50:41707 functor_(std::forward<ForwardFunctor>(functor)),
tzik99de02b2016-07-01 05:54:12708 bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
tzikc1db72652016-07-08 09:42:38709 DCHECK(!IsNull(functor_));
tzik99de02b2016-07-01 05:54:12710 }
[email protected]7296f2762011-11-21 19:23:44711
tzik1fdcca32016-09-14 07:15:00712 template <typename ForwardFunctor, typename... ForwardBoundArgs>
713 explicit BindState(std::false_type,
714 BindStateBase::InvokeFuncStorage invoke_func,
715 ForwardFunctor&& functor,
716 ForwardBoundArgs&&... bound_args)
717 : BindStateBase(invoke_func, &Destroy),
718 functor_(std::forward<ForwardFunctor>(functor)),
719 bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
720 DCHECK(!IsNull(functor_));
721 }
dmichael7d09007e2014-12-18 22:30:11722
Chris Watkins091d6292017-12-13 04:25:58723 ~BindState() = default;
taptede7e804c2015-05-14 08:03:32724
tzik30e0c312016-09-21 08:06:54725 static void Destroy(const BindStateBase* self) {
726 delete static_cast<const BindState*>(self);
taptede7e804c2015-05-14 08:03:32727 }
[email protected]fccef1552011-11-28 22:13:54728};
729
tzik99de02b2016-07-01 05:54:12730// Used to implement MakeBindStateType.
731template <bool is_method, typename Functor, typename... BoundArgs>
732struct MakeBindStateTypeImpl;
733
734template <typename Functor, typename... BoundArgs>
735struct MakeBindStateTypeImpl<false, Functor, BoundArgs...> {
Jeremy Roman35a317432017-08-16 22:20:53736 static_assert(!HasRefCountedTypeAsRawPtr<std::decay_t<BoundArgs>...>::value,
tzik99de02b2016-07-01 05:54:12737 "A parameter is a refcounted type and needs scoped_refptr.");
Jeremy Roman35a317432017-08-16 22:20:53738 using Type = BindState<std::decay_t<Functor>, std::decay_t<BoundArgs>...>;
tzik99de02b2016-07-01 05:54:12739};
740
741template <typename Functor>
742struct MakeBindStateTypeImpl<true, Functor> {
Jeremy Roman35a317432017-08-16 22:20:53743 using Type = BindState<std::decay_t<Functor>>;
tzik99de02b2016-07-01 05:54:12744};
745
746template <typename Functor, typename Receiver, typename... BoundArgs>
747struct MakeBindStateTypeImpl<true, Functor, Receiver, BoundArgs...> {
tzik99de02b2016-07-01 05:54:12748 private:
Jeremy Roman35a317432017-08-16 22:20:53749 using DecayedReceiver = std::decay_t<Receiver>;
tzik99de02b2016-07-01 05:54:12750
tzik4625ac612018-02-28 09:43:55751 static_assert(!std::is_array<std::remove_reference_t<Receiver>>::value,
752 "First bound argument to a method cannot be an array.");
753 static_assert(
754 !std::is_pointer<DecayedReceiver>::value ||
755 IsRefCountedType<std::remove_pointer_t<DecayedReceiver>>::value,
756 "Receivers may not be raw pointers. If using a raw pointer here is safe"
757 " and has no lifetime concerns, use base::Unretained() and document why"
758 " it's safe.");
759 static_assert(!HasRefCountedTypeAsRawPtr<std::decay_t<BoundArgs>...>::value,
760 "A parameter is a refcounted type and needs scoped_refptr.");
761
tzik99de02b2016-07-01 05:54:12762 public:
763 using Type = BindState<
Jeremy Roman35a317432017-08-16 22:20:53764 std::decay_t<Functor>,
765 std::conditional_t<std::is_pointer<DecayedReceiver>::value,
766 scoped_refptr<std::remove_pointer_t<DecayedReceiver>>,
767 DecayedReceiver>,
768 std::decay_t<BoundArgs>...>;
tzik99de02b2016-07-01 05:54:12769};
770
771template <typename Functor, typename... BoundArgs>
tzikae4202e2017-07-31 10:41:54772using MakeBindStateType =
773 typename MakeBindStateTypeImpl<MakeFunctorTraits<Functor>::is_method,
774 Functor,
775 BoundArgs...>::Type;
tzik99de02b2016-07-01 05:54:12776
[email protected]b38d3572011-02-15 01:27:38777} // namespace internal
tzikcaf1d84b2016-06-28 12:22:21778
Peter Kastinga85265e32018-02-15 08:30:23779// An injection point to control |this| pointer behavior on a method invocation.
780// If IsWeakReceiver<> is true_type for |T| and |T| is used for a receiver of a
781// method, base::Bind cancels the method invocation if the receiver is tested as
782// false.
783// E.g. Foo::bar() is not called:
784// struct Foo : base::SupportsWeakPtr<Foo> {
785// void bar() {}
786// };
787//
788// WeakPtr<Foo> oo = nullptr;
789// base::Bind(&Foo::bar, oo).Run();
790template <typename T>
791struct IsWeakReceiver : std::false_type {};
792
793template <typename T>
794struct IsWeakReceiver<internal::ConstRefWrapper<T>> : IsWeakReceiver<T> {};
795
796template <typename T>
797struct IsWeakReceiver<WeakPtr<T>> : std::true_type {};
798
799// An injection point to control how bound objects passed to the target
800// function. BindUnwrapTraits<>::Unwrap() is called for each bound objects right
801// before the target function is invoked.
802template <typename>
803struct BindUnwrapTraits {
804 template <typename T>
805 static T&& Unwrap(T&& o) {
806 return std::forward<T>(o);
807 }
808};
809
810template <typename T>
811struct BindUnwrapTraits<internal::UnretainedWrapper<T>> {
812 static T* Unwrap(const internal::UnretainedWrapper<T>& o) { return o.get(); }
813};
814
815template <typename T>
816struct BindUnwrapTraits<internal::ConstRefWrapper<T>> {
817 static const T& Unwrap(const internal::ConstRefWrapper<T>& o) {
818 return o.get();
819 }
820};
821
822template <typename T>
823struct BindUnwrapTraits<internal::RetainedRefWrapper<T>> {
824 static T* Unwrap(const internal::RetainedRefWrapper<T>& o) { return o.get(); }
825};
826
827template <typename T>
828struct BindUnwrapTraits<internal::OwnedWrapper<T>> {
829 static T* Unwrap(const internal::OwnedWrapper<T>& o) { return o.get(); }
830};
831
832template <typename T>
833struct BindUnwrapTraits<internal::PassedWrapper<T>> {
834 static T Unwrap(const internal::PassedWrapper<T>& o) { return o.Take(); }
835};
836
837// CallbackCancellationTraits allows customization of Callback's cancellation
838// semantics. By default, callbacks are not cancellable. A specialization should
839// set is_cancellable = true and implement an IsCancelled() that returns if the
840// callback should be cancelled.
841template <typename Functor, typename BoundArgsTuple, typename SFINAE>
842struct CallbackCancellationTraits {
843 static constexpr bool is_cancellable = false;
844};
845
846// Specialization for method bound to weak pointer receiver.
847template <typename Functor, typename... BoundArgs>
848struct CallbackCancellationTraits<
849 Functor,
850 std::tuple<BoundArgs...>,
851 std::enable_if_t<
852 internal::IsWeakMethod<internal::FunctorTraits<Functor>::is_method,
853 BoundArgs...>::value>> {
854 static constexpr bool is_cancellable = true;
855
856 template <typename Receiver, typename... Args>
857 static bool IsCancelled(const Functor&,
858 const Receiver& receiver,
859 const Args&...) {
860 return !receiver;
861 }
862};
863
864// Specialization for a nested bind.
865template <typename Signature, typename... BoundArgs>
866struct CallbackCancellationTraits<OnceCallback<Signature>,
867 std::tuple<BoundArgs...>> {
868 static constexpr bool is_cancellable = true;
869
870 template <typename Functor>
871 static bool IsCancelled(const Functor& functor, const BoundArgs&...) {
872 return functor.IsCancelled();
873 }
874};
875
876template <typename Signature, typename... BoundArgs>
877struct CallbackCancellationTraits<RepeatingCallback<Signature>,
878 std::tuple<BoundArgs...>> {
879 static constexpr bool is_cancellable = true;
880
881 template <typename Functor>
882 static bool IsCancelled(const Functor& functor, const BoundArgs&...) {
883 return functor.IsCancelled();
884 }
885};
886
tzikcaf1d84b2016-06-28 12:22:21887// Returns a RunType of bound functor.
888// E.g. MakeUnboundRunType<R(A, B, C), A, B> is evaluated to R(C).
889template <typename Functor, typename... BoundArgs>
890using MakeUnboundRunType =
tzikae4202e2017-07-31 10:41:54891 typename internal::BindTypeHelper<Functor, BoundArgs...>::UnboundRunType;
tzikcaf1d84b2016-06-28 12:22:21892
[email protected]b38d3572011-02-15 01:27:38893} // namespace base
894
895#endif // BASE_BIND_INTERNAL_H_