blob: 9d5720fa48942e5b1d9d1974f5c407c2f2c4c28a [file] [log] [blame]
ajwong@chromium.orge2cca632011-02-15 10:27:38 +09001// 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_
ajwong@chromium.orge2cca632011-02-15 10:27:38 +09007
avia6a6a682015-12-27 07:15:14 +09008#include <stddef.h>
9
vmpstr495da402015-11-18 17:43:26 +090010#include <type_traits>
Jeremy Roman773e7f22017-08-17 00:55:20 +090011#include <utility>
vmpstr495da402015-11-18 17:43:26 +090012
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090013#include "base/bind_helpers.h"
ajwong@chromium.orgfa0ff432011-02-19 08:29:31 +090014#include "base/callback_internal.h"
ajwong@chromium.org27e56852011-10-01 15:31:41 +090015#include "base/memory/raw_scoped_refptr_mismatch_checker.h"
ajwong@chromium.orgc711b822011-05-17 07:35:14 +090016#include "base/memory/weak_ptr.h"
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090017#include "base/template_util.h"
ajwong@chromium.orgcb175342011-02-27 10:25:59 +090018#include "build/build_config.h"
19
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090020namespace base {
21namespace internal {
22
brettw@chromium.org11e3bfd2012-07-13 05:06:40 +090023// See base/callback.h for user documentation.
24//
25//
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +090026// CONCEPTS:
tzik9f27e1f2016-07-01 14:54:12 +090027// Functor -- A movable type representing something that should be called.
28// All function pointers and Callback<> are functors even if the
29// invocation syntax differs.
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +090030// RunType -- A function type (as opposed to function _pointer_ type) for
tzik9f27e1f2016-07-01 14:54:12 +090031// a Callback<>::Run(). Usually just a convenience typedef.
tzikb0632222015-12-15 15:41:49 +090032// (Bound)Args -- A set of types that stores the arguments.
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090033//
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +090034// Types:
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +090035// ForceVoidReturn<> -- Helper class for translating function signatures to
36// equivalent forms with a "void" return type.
tzik9f27e1f2016-07-01 14:54:12 +090037// FunctorTraits<> -- Type traits used to determine the correct RunType and
38// invocation manner for a Functor. This is where function
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +090039// signature adapters are applied.
tzik9f27e1f2016-07-01 14:54:12 +090040// InvokeHelper<> -- Take a Functor + arguments and actully invokes it.
tzik07e99402015-02-06 04:11:26 +090041// Handle the differing syntaxes needed for WeakPtr<>
tzik9f27e1f2016-07-01 14:54:12 +090042// support. This is separate from Invoker to avoid creating
43// multiple version of Invoker<>.
44// Invoker<> -- Unwraps the curried parameters and executes the Functor.
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +090045// BindState<> -- Stores the curried parameters, and is the main entry point
tzik9f27e1f2016-07-01 14:54:12 +090046// into the Bind() system.
ajwong@chromium.orge0648232011-02-19 09:52:15 +090047
tzik31d3fae2016-07-08 18:42:38 +090048template <typename Callable,
49 typename Signature = decltype(&Callable::operator())>
50struct ExtractCallableRunTypeImpl;
51
52template <typename Callable, typename R, typename... Args>
tzikcbc50fc2017-12-02 12:28:58 +090053struct ExtractCallableRunTypeImpl<Callable, R (Callable::*)(Args...)> {
54 using Type = R(Args...);
55};
56
57template <typename Callable, typename R, typename... Args>
58struct ExtractCallableRunTypeImpl<Callable, R (Callable::*)(Args...) const> {
tzik31d3fae2016-07-08 18:42:38 +090059 using Type = R(Args...);
60};
61
62// Evaluated to RunType of the given callable type.
63// Example:
64// auto f = [](int, char*) { return 0.1; };
65// ExtractCallableRunType<decltype(f)>
66// is evaluated to
67// double(int, char*);
68template <typename Callable>
69using ExtractCallableRunType =
70 typename ExtractCallableRunTypeImpl<Callable>::Type;
71
tzikcbc50fc2017-12-02 12:28:58 +090072// IsCallableObject<Functor> is std::true_type if |Functor| has operator().
73// Otherwise, it's std::false_type.
tzik31d3fae2016-07-08 18:42:38 +090074// Example:
tzikcbc50fc2017-12-02 12:28:58 +090075// IsCallableObject<void(*)()>::value is false.
tzik31d3fae2016-07-08 18:42:38 +090076//
77// struct Foo {};
tzikcbc50fc2017-12-02 12:28:58 +090078// IsCallableObject<void(Foo::*)()>::value is false.
tzik31d3fae2016-07-08 18:42:38 +090079//
80// int i = 0;
tzikcbc50fc2017-12-02 12:28:58 +090081// auto f = [i]() {};
82// IsCallableObject<decltype(f)>::value is false.
tzik31d3fae2016-07-08 18:42:38 +090083template <typename Functor, typename SFINAE = void>
tzikcbc50fc2017-12-02 12:28:58 +090084struct IsCallableObject : std::false_type {};
tzik31d3fae2016-07-08 18:42:38 +090085
86template <typename Callable>
tzikcbc50fc2017-12-02 12:28:58 +090087struct IsCallableObject<Callable, void_t<decltype(&Callable::operator())>>
88 : std::true_type {};
tzik31d3fae2016-07-08 18:42:38 +090089
tzik8df08a52014-11-26 16:54:58 +090090// HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw
91// pointer to a RefCounted type.
92// Implementation note: This non-specialized case handles zero-arity case only.
93// Non-zero-arity cases should be handled by the specialization below.
94template <typename... Args>
tzik56bd7652016-03-10 16:17:25 +090095struct HasRefCountedTypeAsRawPtr : std::false_type {};
tzik8df08a52014-11-26 16:54:58 +090096
97// Implementation note: Select true_type if the first parameter is a raw pointer
98// to a RefCounted type. Otherwise, skip the first parameter and check rest of
99// parameters recursively.
100template <typename T, typename... Args>
101struct HasRefCountedTypeAsRawPtr<T, Args...>
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900102 : std::conditional_t<NeedsScopedRefptrButGetsRawPtr<T>::value,
103 std::true_type,
104 HasRefCountedTypeAsRawPtr<Args...>> {};
tzik8df08a52014-11-26 16:54:58 +0900105
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900106// ForceVoidReturn<>
107//
108// Set of templates that support forcing the function return type to void.
109template <typename Sig>
110struct ForceVoidReturn;
111
tzik012481a2014-11-20 19:09:45 +0900112template <typename R, typename... Args>
113struct ForceVoidReturn<R(Args...)> {
tzik9f27e1f2016-07-01 14:54:12 +0900114 using RunType = void(Args...);
ajwong@chromium.org6f015bd2011-11-29 07:13:54 +0900115};
116
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900117// FunctorTraits<>
118//
119// See description at top of file.
tzike6e61952016-11-26 00:56:36 +0900120template <typename Functor, typename SFINAE>
tzik9f27e1f2016-07-01 14:54:12 +0900121struct FunctorTraits;
122
tzikcbc50fc2017-12-02 12:28:58 +0900123// For empty callable types.
tzik31d3fae2016-07-08 18:42:38 +0900124// This specialization is intended to allow binding captureless lambdas by
tzikcbc50fc2017-12-02 12:28:58 +0900125// base::Bind(), based on the fact that captureless lambdas are empty while
126// capturing lambdas are not. This also allows any functors as far as it's an
127// empty class.
128// Example:
129//
130// // Captureless lambdas are allowed.
131// []() {return 42;};
132//
133// // Capturing lambdas are *not* allowed.
134// int x;
135// [x]() {return x;};
136//
137// // Any empty class with operator() is allowed.
138// struct Foo {
139// void operator()() const {}
140// // No non-static member variable and no virtual functions.
141// };
tzik31d3fae2016-07-08 18:42:38 +0900142template <typename Functor>
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900143struct FunctorTraits<Functor,
tzikcbc50fc2017-12-02 12:28:58 +0900144 std::enable_if_t<IsCallableObject<Functor>::value &&
145 std::is_empty<Functor>::value>> {
tzik31d3fae2016-07-08 18:42:38 +0900146 using RunType = ExtractCallableRunType<Functor>;
147 static constexpr bool is_method = false;
148 static constexpr bool is_nullable = false;
149
tzikcbc50fc2017-12-02 12:28:58 +0900150 template <typename RunFunctor, typename... RunArgs>
151 static ExtractReturnType<RunType> Invoke(RunFunctor&& functor,
152 RunArgs&&... args) {
153 return std::forward<RunFunctor>(functor)(std::forward<RunArgs>(args)...);
tzik31d3fae2016-07-08 18:42:38 +0900154 }
155};
156
tzik9f27e1f2016-07-01 14:54:12 +0900157// For functions.
158template <typename R, typename... Args>
159struct FunctorTraits<R (*)(Args...)> {
160 using RunType = R(Args...);
161 static constexpr bool is_method = false;
tzik31d3fae2016-07-08 18:42:38 +0900162 static constexpr bool is_nullable = true;
tzik9f27e1f2016-07-01 14:54:12 +0900163
164 template <typename... RunArgs>
165 static R Invoke(R (*function)(Args...), RunArgs&&... args) {
166 return function(std::forward<RunArgs>(args)...);
167 }
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900168};
169
tzik9f27e1f2016-07-01 14:54:12 +0900170#if defined(OS_WIN) && !defined(ARCH_CPU_X86_64)
171
172// For functions.
173template <typename R, typename... Args>
174struct FunctorTraits<R(__stdcall*)(Args...)> {
175 using RunType = R(Args...);
176 static constexpr bool is_method = false;
tzik31d3fae2016-07-08 18:42:38 +0900177 static constexpr bool is_nullable = true;
tzik9f27e1f2016-07-01 14:54:12 +0900178
179 template <typename... RunArgs>
180 static R Invoke(R(__stdcall* function)(Args...), RunArgs&&... args) {
181 return function(std::forward<RunArgs>(args)...);
182 }
183};
184
185// For functions.
186template <typename R, typename... Args>
187struct FunctorTraits<R(__fastcall*)(Args...)> {
188 using RunType = R(Args...);
189 static constexpr bool is_method = false;
tzik31d3fae2016-07-08 18:42:38 +0900190 static constexpr bool is_nullable = true;
tzik9f27e1f2016-07-01 14:54:12 +0900191
192 template <typename... RunArgs>
193 static R Invoke(R(__fastcall* function)(Args...), RunArgs&&... args) {
194 return function(std::forward<RunArgs>(args)...);
195 }
196};
197
198#endif // defined(OS_WIN) && !defined(ARCH_CPU_X86_64)
199
200// For methods.
201template <typename R, typename Receiver, typename... Args>
202struct FunctorTraits<R (Receiver::*)(Args...)> {
203 using RunType = R(Receiver*, Args...);
204 static constexpr bool is_method = true;
tzik31d3fae2016-07-08 18:42:38 +0900205 static constexpr bool is_nullable = true;
tzik9f27e1f2016-07-01 14:54:12 +0900206
207 template <typename ReceiverPtr, typename... RunArgs>
208 static R Invoke(R (Receiver::*method)(Args...),
209 ReceiverPtr&& receiver_ptr,
210 RunArgs&&... args) {
tzik8bcf5ef2017-06-14 15:57:01 +0900211 return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
tzik9f27e1f2016-07-01 14:54:12 +0900212 }
213};
214
215// For const methods.
216template <typename R, typename Receiver, typename... Args>
217struct FunctorTraits<R (Receiver::*)(Args...) const> {
218 using RunType = R(const Receiver*, Args...);
219 static constexpr bool is_method = true;
tzik31d3fae2016-07-08 18:42:38 +0900220 static constexpr bool is_nullable = true;
tzik9f27e1f2016-07-01 14:54:12 +0900221
222 template <typename ReceiverPtr, typename... RunArgs>
223 static R Invoke(R (Receiver::*method)(Args...) const,
224 ReceiverPtr&& receiver_ptr,
225 RunArgs&&... args) {
tzik8bcf5ef2017-06-14 15:57:01 +0900226 return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
tzik9f27e1f2016-07-01 14:54:12 +0900227 }
228};
229
230// For IgnoreResults.
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900231template <typename T>
tzik9f27e1f2016-07-01 14:54:12 +0900232struct FunctorTraits<IgnoreResultHelper<T>> : FunctorTraits<T> {
tzik260fab52015-12-19 18:18:46 +0900233 using RunType =
tzik9f27e1f2016-07-01 14:54:12 +0900234 typename ForceVoidReturn<typename FunctorTraits<T>::RunType>::RunType;
235
236 template <typename IgnoreResultType, typename... RunArgs>
237 static void Invoke(IgnoreResultType&& ignore_result_helper,
238 RunArgs&&... args) {
tzike467aa42016-08-31 20:50:41 +0900239 FunctorTraits<T>::Invoke(
240 std::forward<IgnoreResultType>(ignore_result_helper).functor_,
241 std::forward<RunArgs>(args)...);
tzik9f27e1f2016-07-01 14:54:12 +0900242 }
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900243};
244
tzik57dfb642017-08-29 04:08:52 +0900245// For OnceCallbacks.
246template <typename R, typename... Args>
247struct FunctorTraits<OnceCallback<R(Args...)>> {
248 using RunType = R(Args...);
249 static constexpr bool is_method = false;
250 static constexpr bool is_nullable = true;
251
252 template <typename CallbackType, typename... RunArgs>
253 static R Invoke(CallbackType&& callback, RunArgs&&... args) {
254 DCHECK(!callback.is_null());
255 return std::forward<CallbackType>(callback).Run(
256 std::forward<RunArgs>(args)...);
257 }
258};
259
260// For RepeatingCallbacks.
261template <typename R, typename... Args>
262struct FunctorTraits<RepeatingCallback<R(Args...)>> {
tzik9f27e1f2016-07-01 14:54:12 +0900263 using RunType = R(Args...);
264 static constexpr bool is_method = false;
tzik31d3fae2016-07-08 18:42:38 +0900265 static constexpr bool is_nullable = true;
tzik9f27e1f2016-07-01 14:54:12 +0900266
267 template <typename CallbackType, typename... RunArgs>
268 static R Invoke(CallbackType&& callback, RunArgs&&... args) {
269 DCHECK(!callback.is_null());
270 return std::forward<CallbackType>(callback).Run(
271 std::forward<RunArgs>(args)...);
272 }
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900273};
274
tzik103f4732017-07-31 19:41:54 +0900275template <typename Functor>
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900276using MakeFunctorTraits = FunctorTraits<std::decay_t<Functor>>;
tzik103f4732017-07-31 19:41:54 +0900277
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900278// InvokeHelper<>
279//
tzik9f27e1f2016-07-01 14:54:12 +0900280// There are 2 logical InvokeHelper<> specializations: normal, WeakCalls.
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900281//
282// The normal type just calls the underlying runnable.
283//
tzik9f27e1f2016-07-01 14:54:12 +0900284// WeakCalls need special syntax that is applied to the first argument to check
285// if they should no-op themselves.
tzike1ad6f62016-06-01 17:22:51 +0900286template <bool is_weak_call, typename ReturnType>
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900287struct InvokeHelper;
288
tzike1ad6f62016-06-01 17:22:51 +0900289template <typename ReturnType>
290struct InvokeHelper<false, ReturnType> {
tzik9f27e1f2016-07-01 14:54:12 +0900291 template <typename Functor, typename... RunArgs>
292 static inline ReturnType MakeItSo(Functor&& functor, RunArgs&&... args) {
tzik103f4732017-07-31 19:41:54 +0900293 using Traits = MakeFunctorTraits<Functor>;
tzik9f27e1f2016-07-01 14:54:12 +0900294 return Traits::Invoke(std::forward<Functor>(functor),
295 std::forward<RunArgs>(args)...);
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900296 }
297};
298
tzike1ad6f62016-06-01 17:22:51 +0900299template <typename ReturnType>
300struct InvokeHelper<true, ReturnType> {
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900301 // WeakCalls are only supported for functions with a void return type.
302 // Otherwise, the function result would be undefined if the the WeakPtr<>
303 // is invalidated.
tzik56bd7652016-03-10 16:17:25 +0900304 static_assert(std::is_void<ReturnType>::value,
avi486c61f2015-11-24 23:26:24 +0900305 "weak_ptrs can only bind to methods without return values");
ajwong@chromium.orga7e74822011-03-24 11:02:17 +0900306
tzik9f27e1f2016-07-01 14:54:12 +0900307 template <typename Functor, typename BoundWeakPtr, typename... RunArgs>
308 static inline void MakeItSo(Functor&& functor,
tzik6bb5cb42016-07-14 21:12:06 +0900309 BoundWeakPtr&& weak_ptr,
tzik9f27e1f2016-07-01 14:54:12 +0900310 RunArgs&&... args) {
311 if (!weak_ptr)
312 return;
tzik103f4732017-07-31 19:41:54 +0900313 using Traits = MakeFunctorTraits<Functor>;
tzik9f27e1f2016-07-01 14:54:12 +0900314 Traits::Invoke(std::forward<Functor>(functor),
315 std::forward<BoundWeakPtr>(weak_ptr),
316 std::forward<RunArgs>(args)...);
317 }
318};
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900319
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900320// Invoker<>
321//
322// See description at the top of the file.
tzikfa6c9852016-06-28 21:22:21 +0900323template <typename StorageType, typename UnboundRunType>
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900324struct Invoker;
325
tzikfa6c9852016-06-28 21:22:21 +0900326template <typename StorageType, typename R, typename... UnboundArgs>
327struct Invoker<StorageType, R(UnboundArgs...)> {
Vladislav Kuzkokov12367422017-11-09 06:31:08 +0900328 static R RunOnce(BindStateBase* base,
329 PassingTraitsType<UnboundArgs>... unbound_args) {
tzikc60a8122016-09-13 14:28:59 +0900330 // Local references to make debugger stepping easier. If in a debugger,
331 // you really want to warp ahead and step through the
332 // InvokeHelper<>::MakeItSo() call below.
333 StorageType* storage = static_cast<StorageType*>(base);
334 static constexpr size_t num_bound_args =
335 std::tuple_size<decltype(storage->bound_args_)>::value;
336 return RunImpl(std::move(storage->functor_),
337 std::move(storage->bound_args_),
Jeremy Roman773e7f22017-08-17 00:55:20 +0900338 std::make_index_sequence<num_bound_args>(),
tzikc60a8122016-09-13 14:28:59 +0900339 std::forward<UnboundArgs>(unbound_args)...);
340 }
341
Vladislav Kuzkokov12367422017-11-09 06:31:08 +0900342 static R Run(BindStateBase* base,
343 PassingTraitsType<UnboundArgs>... unbound_args) {
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900344 // Local references to make debugger stepping easier. If in a debugger,
345 // you really want to warp ahead and step through the
346 // InvokeHelper<>::MakeItSo() call below.
tzikfa6c9852016-06-28 21:22:21 +0900347 const StorageType* storage = static_cast<StorageType*>(base);
348 static constexpr size_t num_bound_args =
349 std::tuple_size<decltype(storage->bound_args_)>::value;
Jeremy Roman773e7f22017-08-17 00:55:20 +0900350 return RunImpl(storage->functor_, storage->bound_args_,
351 std::make_index_sequence<num_bound_args>(),
tzikfa6c9852016-06-28 21:22:21 +0900352 std::forward<UnboundArgs>(unbound_args)...);
353 }
354
tzik9f27e1f2016-07-01 14:54:12 +0900355 private:
356 template <typename Functor, typename BoundArgsTuple, size_t... indices>
357 static inline R RunImpl(Functor&& functor,
tzikfa6c9852016-06-28 21:22:21 +0900358 BoundArgsTuple&& bound,
Jeremy Roman773e7f22017-08-17 00:55:20 +0900359 std::index_sequence<indices...>,
tzikfa6c9852016-06-28 21:22:21 +0900360 UnboundArgs&&... unbound_args) {
tzik103f4732017-07-31 19:41:54 +0900361 static constexpr bool is_method = MakeFunctorTraits<Functor>::is_method;
tzikfa6c9852016-06-28 21:22:21 +0900362
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900363 using DecayedArgsTuple = std::decay_t<BoundArgsTuple>;
tzikfa6c9852016-06-28 21:22:21 +0900364 static constexpr bool is_weak_call =
365 IsWeakMethod<is_method,
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900366 std::tuple_element_t<indices, DecayedArgsTuple>...>();
tzikfa6c9852016-06-28 21:22:21 +0900367
tzike1ad6f62016-06-01 17:22:51 +0900368 return InvokeHelper<is_weak_call, R>::MakeItSo(
tzik9f27e1f2016-07-01 14:54:12 +0900369 std::forward<Functor>(functor),
tzik3c147c42017-04-06 06:45:03 +0900370 Unwrap(std::get<indices>(std::forward<BoundArgsTuple>(bound)))...,
tzik0d4bab22016-03-09 14:46:05 +0900371 std::forward<UnboundArgs>(unbound_args)...);
ajwong@chromium.org6f015bd2011-11-29 07:13:54 +0900372 }
373};
374
tzik103f4732017-07-31 19:41:54 +0900375// Extracts necessary type info from Functor and BoundArgs.
376// Used to implement MakeUnboundRunType, BindOnce and BindRepeating.
tzikfa6c9852016-06-28 21:22:21 +0900377template <typename Functor, typename... BoundArgs>
tzik103f4732017-07-31 19:41:54 +0900378struct BindTypeHelper {
379 static constexpr size_t num_bounds = sizeof...(BoundArgs);
380 using FunctorTraits = MakeFunctorTraits<Functor>;
381
382 // Example:
383 // When Functor is `double (Foo::*)(int, const std::string&)`, and BoundArgs
384 // is a template pack of `Foo*` and `int16_t`:
385 // - RunType is `double(Foo*, int, const std::string&)`,
386 // - ReturnType is `double`,
387 // - RunParamsList is `TypeList<Foo*, int, const std::string&>`,
388 // - BoundParamsList is `TypeList<Foo*, int>`,
389 // - UnboundParamsList is `TypeList<const std::string&>`,
390 // - BoundArgsList is `TypeList<Foo*, int16_t>`,
391 // - UnboundRunType is `double(const std::string&)`.
392 using RunType = typename FunctorTraits::RunType;
tzikfa6c9852016-06-28 21:22:21 +0900393 using ReturnType = ExtractReturnType<RunType>;
tzik103f4732017-07-31 19:41:54 +0900394
395 using RunParamsList = ExtractArgs<RunType>;
396 using BoundParamsList = TakeTypeListItem<num_bounds, RunParamsList>;
397 using UnboundParamsList = DropTypeListItem<num_bounds, RunParamsList>;
398
399 using BoundArgsList = TypeList<BoundArgs...>;
400
401 using UnboundRunType = MakeFunctionType<ReturnType, UnboundParamsList>;
tzikfa6c9852016-06-28 21:22:21 +0900402};
tzik103f4732017-07-31 19:41:54 +0900403
tzik31d3fae2016-07-08 18:42:38 +0900404template <typename Functor>
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900405std::enable_if_t<FunctorTraits<Functor>::is_nullable, bool> IsNull(
406 const Functor& functor) {
tzik31d3fae2016-07-08 18:42:38 +0900407 return !functor;
408}
409
410template <typename Functor>
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900411std::enable_if_t<!FunctorTraits<Functor>::is_nullable, bool> IsNull(
412 const Functor&) {
tzik31d3fae2016-07-08 18:42:38 +0900413 return false;
414}
tzikfa6c9852016-06-28 21:22:21 +0900415
tzike6e61952016-11-26 00:56:36 +0900416// Used by ApplyCancellationTraits below.
417template <typename Functor, typename BoundArgsTuple, size_t... indices>
418bool ApplyCancellationTraitsImpl(const Functor& functor,
419 const BoundArgsTuple& bound_args,
Jeremy Roman773e7f22017-08-17 00:55:20 +0900420 std::index_sequence<indices...>) {
tzike6e61952016-11-26 00:56:36 +0900421 return CallbackCancellationTraits<Functor, BoundArgsTuple>::IsCancelled(
tzik3c147c42017-04-06 06:45:03 +0900422 functor, std::get<indices>(bound_args)...);
tzike6e61952016-11-26 00:56:36 +0900423}
tzik058872d2016-09-08 19:58:53 +0900424
tzike6e61952016-11-26 00:56:36 +0900425// Relays |base| to corresponding CallbackCancellationTraits<>::Run(). Returns
426// true if the callback |base| represents is canceled.
427template <typename BindStateType>
428bool ApplyCancellationTraits(const BindStateBase* base) {
429 const BindStateType* storage = static_cast<const BindStateType*>(base);
430 static constexpr size_t num_bound_args =
431 std::tuple_size<decltype(storage->bound_args_)>::value;
Jeremy Roman773e7f22017-08-17 00:55:20 +0900432 return ApplyCancellationTraitsImpl(
433 storage->functor_, storage->bound_args_,
434 std::make_index_sequence<num_bound_args>());
tzik058872d2016-09-08 19:58:53 +0900435};
436
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900437// BindState<>
438//
tzik9f27e1f2016-07-01 14:54:12 +0900439// This stores all the state passed into Bind().
440template <typename Functor, typename... BoundArgs>
441struct BindState final : BindStateBase {
tzik1d2f3632016-09-14 16:15:00 +0900442 using IsCancellable = std::integral_constant<
tzike6e61952016-11-26 00:56:36 +0900443 bool,
444 CallbackCancellationTraits<Functor,
445 std::tuple<BoundArgs...>>::is_cancellable>;
tzik1d2f3632016-09-14 16:15:00 +0900446
tzikb4ec92d2016-07-08 23:14:01 +0900447 template <typename ForwardFunctor, typename... ForwardBoundArgs>
tzikd0473e62016-09-08 14:45:38 +0900448 explicit BindState(BindStateBase::InvokeFuncStorage invoke_func,
449 ForwardFunctor&& functor,
450 ForwardBoundArgs&&... bound_args)
tzike6e61952016-11-26 00:56:36 +0900451 // IsCancellable is std::false_type if
452 // CallbackCancellationTraits<>::IsCancelled returns always false.
453 // Otherwise, it's std::true_type.
tzik1d2f3632016-09-14 16:15:00 +0900454 : BindState(IsCancellable{},
455 invoke_func,
456 std::forward<ForwardFunctor>(functor),
tzikcbc50fc2017-12-02 12:28:58 +0900457 std::forward<ForwardBoundArgs>(bound_args)...) {}
tzik1d2f3632016-09-14 16:15:00 +0900458
459 Functor functor_;
460 std::tuple<BoundArgs...> bound_args_;
461
462 private:
463 template <typename ForwardFunctor, typename... ForwardBoundArgs>
464 explicit BindState(std::true_type,
465 BindStateBase::InvokeFuncStorage invoke_func,
466 ForwardFunctor&& functor,
467 ForwardBoundArgs&&... bound_args)
tzike6e61952016-11-26 00:56:36 +0900468 : BindStateBase(invoke_func,
469 &Destroy,
470 &ApplyCancellationTraits<BindState>),
tzike467aa42016-08-31 20:50:41 +0900471 functor_(std::forward<ForwardFunctor>(functor)),
tzik9f27e1f2016-07-01 14:54:12 +0900472 bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
tzik31d3fae2016-07-08 18:42:38 +0900473 DCHECK(!IsNull(functor_));
tzik9f27e1f2016-07-01 14:54:12 +0900474 }
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900475
tzik1d2f3632016-09-14 16:15:00 +0900476 template <typename ForwardFunctor, typename... ForwardBoundArgs>
477 explicit BindState(std::false_type,
478 BindStateBase::InvokeFuncStorage invoke_func,
479 ForwardFunctor&& functor,
480 ForwardBoundArgs&&... bound_args)
481 : BindStateBase(invoke_func, &Destroy),
482 functor_(std::forward<ForwardFunctor>(functor)),
483 bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
484 DCHECK(!IsNull(functor_));
485 }
dmichael2f7bc202014-12-19 07:30:11 +0900486
Chris Watkins653cd662017-12-13 13:25:58 +0900487 ~BindState() = default;
tapted9cef4212015-05-14 17:03:32 +0900488
tzikfecd1862016-09-21 17:06:54 +0900489 static void Destroy(const BindStateBase* self) {
490 delete static_cast<const BindState*>(self);
tapted9cef4212015-05-14 17:03:32 +0900491 }
ajwong@chromium.org6f015bd2011-11-29 07:13:54 +0900492};
493
tzik9f27e1f2016-07-01 14:54:12 +0900494// Used to implement MakeBindStateType.
495template <bool is_method, typename Functor, typename... BoundArgs>
496struct MakeBindStateTypeImpl;
497
498template <typename Functor, typename... BoundArgs>
499struct MakeBindStateTypeImpl<false, Functor, BoundArgs...> {
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900500 static_assert(!HasRefCountedTypeAsRawPtr<std::decay_t<BoundArgs>...>::value,
tzik9f27e1f2016-07-01 14:54:12 +0900501 "A parameter is a refcounted type and needs scoped_refptr.");
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900502 using Type = BindState<std::decay_t<Functor>, std::decay_t<BoundArgs>...>;
tzik9f27e1f2016-07-01 14:54:12 +0900503};
504
505template <typename Functor>
506struct MakeBindStateTypeImpl<true, Functor> {
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900507 using Type = BindState<std::decay_t<Functor>>;
tzik9f27e1f2016-07-01 14:54:12 +0900508};
509
510template <typename Functor, typename Receiver, typename... BoundArgs>
511struct MakeBindStateTypeImpl<true, Functor, Receiver, BoundArgs...> {
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900512 static_assert(!std::is_array<std::remove_reference_t<Receiver>>::value,
513 "First bound argument to a method cannot be an array.");
514 static_assert(!HasRefCountedTypeAsRawPtr<std::decay_t<BoundArgs>...>::value,
tzik9f27e1f2016-07-01 14:54:12 +0900515 "A parameter is a refcounted type and needs scoped_refptr.");
516
517 private:
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900518 using DecayedReceiver = std::decay_t<Receiver>;
tzik9f27e1f2016-07-01 14:54:12 +0900519
520 public:
521 using Type = BindState<
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900522 std::decay_t<Functor>,
523 std::conditional_t<std::is_pointer<DecayedReceiver>::value,
524 scoped_refptr<std::remove_pointer_t<DecayedReceiver>>,
525 DecayedReceiver>,
526 std::decay_t<BoundArgs>...>;
tzik9f27e1f2016-07-01 14:54:12 +0900527};
528
529template <typename Functor, typename... BoundArgs>
tzik103f4732017-07-31 19:41:54 +0900530using MakeBindStateType =
531 typename MakeBindStateTypeImpl<MakeFunctorTraits<Functor>::is_method,
532 Functor,
533 BoundArgs...>::Type;
tzik9f27e1f2016-07-01 14:54:12 +0900534
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900535} // namespace internal
tzikfa6c9852016-06-28 21:22:21 +0900536
537// Returns a RunType of bound functor.
538// E.g. MakeUnboundRunType<R(A, B, C), A, B> is evaluated to R(C).
539template <typename Functor, typename... BoundArgs>
540using MakeUnboundRunType =
tzik103f4732017-07-31 19:41:54 +0900541 typename internal::BindTypeHelper<Functor, BoundArgs...>::UnboundRunType;
tzikfa6c9852016-06-28 21:22:21 +0900542
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900543} // namespace base
544
545#endif // BASE_BIND_INTERNAL_H_