blob: c36b1535270dcb836ba8fa49718ca1c29860165b [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>
53struct ExtractCallableRunTypeImpl<Callable, R(Callable::*)(Args...) const> {
54 using Type = R(Args...);
55};
56
57// Evaluated to RunType of the given callable type.
58// Example:
59// auto f = [](int, char*) { return 0.1; };
60// ExtractCallableRunType<decltype(f)>
61// is evaluated to
62// double(int, char*);
63template <typename Callable>
64using ExtractCallableRunType =
65 typename ExtractCallableRunTypeImpl<Callable>::Type;
66
67// IsConvertibleToRunType<Functor> is std::true_type if |Functor| has operator()
68// and convertible to the corresponding function pointer. Otherwise, it's
69// std::false_type.
70// Example:
71// IsConvertibleToRunType<void(*)()>::value is false.
72//
73// struct Foo {};
74// IsConvertibleToRunType<void(Foo::*)()>::value is false.
75//
76// auto f = []() {};
77// IsConvertibleToRunType<decltype(f)>::value is true.
78//
79// int i = 0;
80// auto g = [i]() {};
81// IsConvertibleToRunType<decltype(g)>::value is false.
82template <typename Functor, typename SFINAE = void>
83struct IsConvertibleToRunType : std::false_type {};
84
85template <typename Callable>
86struct IsConvertibleToRunType<Callable, void_t<decltype(&Callable::operator())>>
87 : std::is_convertible<Callable, ExtractCallableRunType<Callable>*> {};
88
tzik8df08a52014-11-26 16:54:58 +090089// HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw
90// pointer to a RefCounted type.
91// Implementation note: This non-specialized case handles zero-arity case only.
92// Non-zero-arity cases should be handled by the specialization below.
93template <typename... Args>
tzik56bd7652016-03-10 16:17:25 +090094struct HasRefCountedTypeAsRawPtr : std::false_type {};
tzik8df08a52014-11-26 16:54:58 +090095
96// Implementation note: Select true_type if the first parameter is a raw pointer
97// to a RefCounted type. Otherwise, skip the first parameter and check rest of
98// parameters recursively.
99template <typename T, typename... Args>
100struct HasRefCountedTypeAsRawPtr<T, Args...>
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900101 : std::conditional_t<NeedsScopedRefptrButGetsRawPtr<T>::value,
102 std::true_type,
103 HasRefCountedTypeAsRawPtr<Args...>> {};
tzik8df08a52014-11-26 16:54:58 +0900104
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900105// ForceVoidReturn<>
106//
107// Set of templates that support forcing the function return type to void.
108template <typename Sig>
109struct ForceVoidReturn;
110
tzik012481a2014-11-20 19:09:45 +0900111template <typename R, typename... Args>
112struct ForceVoidReturn<R(Args...)> {
tzik9f27e1f2016-07-01 14:54:12 +0900113 using RunType = void(Args...);
ajwong@chromium.org6f015bd2011-11-29 07:13:54 +0900114};
115
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900116// FunctorTraits<>
117//
118// See description at top of file.
tzike6e61952016-11-26 00:56:36 +0900119template <typename Functor, typename SFINAE>
tzik9f27e1f2016-07-01 14:54:12 +0900120struct FunctorTraits;
121
tzik31d3fae2016-07-08 18:42:38 +0900122// For a callable type that is convertible to the corresponding function type.
123// This specialization is intended to allow binding captureless lambdas by
124// base::Bind(), based on the fact that captureless lambdas can be convertible
125// to the function type while capturing lambdas can't.
126template <typename Functor>
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900127struct FunctorTraits<Functor,
128 std::enable_if_t<IsConvertibleToRunType<Functor>::value>> {
tzik31d3fae2016-07-08 18:42:38 +0900129 using RunType = ExtractCallableRunType<Functor>;
130 static constexpr bool is_method = false;
131 static constexpr bool is_nullable = false;
132
133 template <typename... RunArgs>
134 static ExtractReturnType<RunType>
135 Invoke(const Functor& functor, RunArgs&&... args) {
136 return functor(std::forward<RunArgs>(args)...);
137 }
138};
139
tzik9f27e1f2016-07-01 14:54:12 +0900140// For functions.
141template <typename R, typename... Args>
142struct FunctorTraits<R (*)(Args...)> {
143 using RunType = R(Args...);
144 static constexpr bool is_method = false;
tzik31d3fae2016-07-08 18:42:38 +0900145 static constexpr bool is_nullable = true;
tzik9f27e1f2016-07-01 14:54:12 +0900146
147 template <typename... RunArgs>
148 static R Invoke(R (*function)(Args...), RunArgs&&... args) {
149 return function(std::forward<RunArgs>(args)...);
150 }
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900151};
152
tzik9f27e1f2016-07-01 14:54:12 +0900153#if defined(OS_WIN) && !defined(ARCH_CPU_X86_64)
154
155// For functions.
156template <typename R, typename... Args>
157struct FunctorTraits<R(__stdcall*)(Args...)> {
158 using RunType = R(Args...);
159 static constexpr bool is_method = false;
tzik31d3fae2016-07-08 18:42:38 +0900160 static constexpr bool is_nullable = true;
tzik9f27e1f2016-07-01 14:54:12 +0900161
162 template <typename... RunArgs>
163 static R Invoke(R(__stdcall* function)(Args...), RunArgs&&... args) {
164 return function(std::forward<RunArgs>(args)...);
165 }
166};
167
168// For functions.
169template <typename R, typename... Args>
170struct FunctorTraits<R(__fastcall*)(Args...)> {
171 using RunType = R(Args...);
172 static constexpr bool is_method = false;
tzik31d3fae2016-07-08 18:42:38 +0900173 static constexpr bool is_nullable = true;
tzik9f27e1f2016-07-01 14:54:12 +0900174
175 template <typename... RunArgs>
176 static R Invoke(R(__fastcall* function)(Args...), RunArgs&&... args) {
177 return function(std::forward<RunArgs>(args)...);
178 }
179};
180
181#endif // defined(OS_WIN) && !defined(ARCH_CPU_X86_64)
182
183// For methods.
184template <typename R, typename Receiver, typename... Args>
185struct FunctorTraits<R (Receiver::*)(Args...)> {
186 using RunType = R(Receiver*, Args...);
187 static constexpr bool is_method = true;
tzik31d3fae2016-07-08 18:42:38 +0900188 static constexpr bool is_nullable = true;
tzik9f27e1f2016-07-01 14:54:12 +0900189
190 template <typename ReceiverPtr, typename... RunArgs>
191 static R Invoke(R (Receiver::*method)(Args...),
192 ReceiverPtr&& receiver_ptr,
193 RunArgs&&... args) {
tzik8bcf5ef2017-06-14 15:57:01 +0900194 return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
tzik9f27e1f2016-07-01 14:54:12 +0900195 }
196};
197
198// For const methods.
199template <typename R, typename Receiver, typename... Args>
200struct FunctorTraits<R (Receiver::*)(Args...) const> {
201 using RunType = R(const Receiver*, Args...);
202 static constexpr bool is_method = true;
tzik31d3fae2016-07-08 18:42:38 +0900203 static constexpr bool is_nullable = true;
tzik9f27e1f2016-07-01 14:54:12 +0900204
205 template <typename ReceiverPtr, typename... RunArgs>
206 static R Invoke(R (Receiver::*method)(Args...) const,
207 ReceiverPtr&& receiver_ptr,
208 RunArgs&&... args) {
tzik8bcf5ef2017-06-14 15:57:01 +0900209 return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
tzik9f27e1f2016-07-01 14:54:12 +0900210 }
211};
212
213// For IgnoreResults.
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900214template <typename T>
tzik9f27e1f2016-07-01 14:54:12 +0900215struct FunctorTraits<IgnoreResultHelper<T>> : FunctorTraits<T> {
tzik260fab52015-12-19 18:18:46 +0900216 using RunType =
tzik9f27e1f2016-07-01 14:54:12 +0900217 typename ForceVoidReturn<typename FunctorTraits<T>::RunType>::RunType;
218
219 template <typename IgnoreResultType, typename... RunArgs>
220 static void Invoke(IgnoreResultType&& ignore_result_helper,
221 RunArgs&&... args) {
tzike467aa42016-08-31 20:50:41 +0900222 FunctorTraits<T>::Invoke(
223 std::forward<IgnoreResultType>(ignore_result_helper).functor_,
224 std::forward<RunArgs>(args)...);
tzik9f27e1f2016-07-01 14:54:12 +0900225 }
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900226};
227
tzik9f27e1f2016-07-01 14:54:12 +0900228// For Callbacks.
tzikc60a8122016-09-13 14:28:59 +0900229template <typename R, typename... Args,
230 CopyMode copy_mode, RepeatMode repeat_mode>
231struct FunctorTraits<Callback<R(Args...), copy_mode, repeat_mode>> {
tzik9f27e1f2016-07-01 14:54:12 +0900232 using RunType = R(Args...);
233 static constexpr bool is_method = false;
tzik31d3fae2016-07-08 18:42:38 +0900234 static constexpr bool is_nullable = true;
tzik9f27e1f2016-07-01 14:54:12 +0900235
236 template <typename CallbackType, typename... RunArgs>
237 static R Invoke(CallbackType&& callback, RunArgs&&... args) {
238 DCHECK(!callback.is_null());
239 return std::forward<CallbackType>(callback).Run(
240 std::forward<RunArgs>(args)...);
241 }
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900242};
243
tzik103f4732017-07-31 19:41:54 +0900244template <typename Functor>
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900245using MakeFunctorTraits = FunctorTraits<std::decay_t<Functor>>;
tzik103f4732017-07-31 19:41:54 +0900246
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900247// InvokeHelper<>
248//
tzik9f27e1f2016-07-01 14:54:12 +0900249// There are 2 logical InvokeHelper<> specializations: normal, WeakCalls.
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900250//
251// The normal type just calls the underlying runnable.
252//
tzik9f27e1f2016-07-01 14:54:12 +0900253// WeakCalls need special syntax that is applied to the first argument to check
254// if they should no-op themselves.
tzike1ad6f62016-06-01 17:22:51 +0900255template <bool is_weak_call, typename ReturnType>
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900256struct InvokeHelper;
257
tzike1ad6f62016-06-01 17:22:51 +0900258template <typename ReturnType>
259struct InvokeHelper<false, ReturnType> {
tzik9f27e1f2016-07-01 14:54:12 +0900260 template <typename Functor, typename... RunArgs>
261 static inline ReturnType MakeItSo(Functor&& functor, RunArgs&&... args) {
tzik103f4732017-07-31 19:41:54 +0900262 using Traits = MakeFunctorTraits<Functor>;
tzik9f27e1f2016-07-01 14:54:12 +0900263 return Traits::Invoke(std::forward<Functor>(functor),
264 std::forward<RunArgs>(args)...);
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900265 }
266};
267
tzike1ad6f62016-06-01 17:22:51 +0900268template <typename ReturnType>
269struct InvokeHelper<true, ReturnType> {
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900270 // WeakCalls are only supported for functions with a void return type.
271 // Otherwise, the function result would be undefined if the the WeakPtr<>
272 // is invalidated.
tzik56bd7652016-03-10 16:17:25 +0900273 static_assert(std::is_void<ReturnType>::value,
avi486c61f2015-11-24 23:26:24 +0900274 "weak_ptrs can only bind to methods without return values");
ajwong@chromium.orga7e74822011-03-24 11:02:17 +0900275
tzik9f27e1f2016-07-01 14:54:12 +0900276 template <typename Functor, typename BoundWeakPtr, typename... RunArgs>
277 static inline void MakeItSo(Functor&& functor,
tzik6bb5cb42016-07-14 21:12:06 +0900278 BoundWeakPtr&& weak_ptr,
tzik9f27e1f2016-07-01 14:54:12 +0900279 RunArgs&&... args) {
280 if (!weak_ptr)
281 return;
tzik103f4732017-07-31 19:41:54 +0900282 using Traits = MakeFunctorTraits<Functor>;
tzik9f27e1f2016-07-01 14:54:12 +0900283 Traits::Invoke(std::forward<Functor>(functor),
284 std::forward<BoundWeakPtr>(weak_ptr),
285 std::forward<RunArgs>(args)...);
286 }
287};
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900288
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900289// Invoker<>
290//
291// See description at the top of the file.
tzikfa6c9852016-06-28 21:22:21 +0900292template <typename StorageType, typename UnboundRunType>
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900293struct Invoker;
294
tzikfa6c9852016-06-28 21:22:21 +0900295template <typename StorageType, typename R, typename... UnboundArgs>
296struct Invoker<StorageType, R(UnboundArgs...)> {
tzikc60a8122016-09-13 14:28:59 +0900297 static R RunOnce(BindStateBase* base, UnboundArgs&&... unbound_args) {
298 // Local references to make debugger stepping easier. If in a debugger,
299 // you really want to warp ahead and step through the
300 // InvokeHelper<>::MakeItSo() call below.
301 StorageType* storage = static_cast<StorageType*>(base);
302 static constexpr size_t num_bound_args =
303 std::tuple_size<decltype(storage->bound_args_)>::value;
304 return RunImpl(std::move(storage->functor_),
305 std::move(storage->bound_args_),
Jeremy Roman773e7f22017-08-17 00:55:20 +0900306 std::make_index_sequence<num_bound_args>(),
tzikc60a8122016-09-13 14:28:59 +0900307 std::forward<UnboundArgs>(unbound_args)...);
308 }
309
tzik0d4bab22016-03-09 14:46:05 +0900310 static R Run(BindStateBase* base, UnboundArgs&&... unbound_args) {
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900311 // Local references to make debugger stepping easier. If in a debugger,
312 // you really want to warp ahead and step through the
313 // InvokeHelper<>::MakeItSo() call below.
tzikfa6c9852016-06-28 21:22:21 +0900314 const StorageType* storage = static_cast<StorageType*>(base);
315 static constexpr size_t num_bound_args =
316 std::tuple_size<decltype(storage->bound_args_)>::value;
Jeremy Roman773e7f22017-08-17 00:55:20 +0900317 return RunImpl(storage->functor_, storage->bound_args_,
318 std::make_index_sequence<num_bound_args>(),
tzikfa6c9852016-06-28 21:22:21 +0900319 std::forward<UnboundArgs>(unbound_args)...);
320 }
321
tzik9f27e1f2016-07-01 14:54:12 +0900322 private:
323 template <typename Functor, typename BoundArgsTuple, size_t... indices>
324 static inline R RunImpl(Functor&& functor,
tzikfa6c9852016-06-28 21:22:21 +0900325 BoundArgsTuple&& bound,
Jeremy Roman773e7f22017-08-17 00:55:20 +0900326 std::index_sequence<indices...>,
tzikfa6c9852016-06-28 21:22:21 +0900327 UnboundArgs&&... unbound_args) {
tzik103f4732017-07-31 19:41:54 +0900328 static constexpr bool is_method = MakeFunctorTraits<Functor>::is_method;
tzikfa6c9852016-06-28 21:22:21 +0900329
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900330 using DecayedArgsTuple = std::decay_t<BoundArgsTuple>;
tzikfa6c9852016-06-28 21:22:21 +0900331 static constexpr bool is_weak_call =
332 IsWeakMethod<is_method,
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900333 std::tuple_element_t<indices, DecayedArgsTuple>...>();
tzikfa6c9852016-06-28 21:22:21 +0900334
tzike1ad6f62016-06-01 17:22:51 +0900335 return InvokeHelper<is_weak_call, R>::MakeItSo(
tzik9f27e1f2016-07-01 14:54:12 +0900336 std::forward<Functor>(functor),
tzik3c147c42017-04-06 06:45:03 +0900337 Unwrap(std::get<indices>(std::forward<BoundArgsTuple>(bound)))...,
tzik0d4bab22016-03-09 14:46:05 +0900338 std::forward<UnboundArgs>(unbound_args)...);
ajwong@chromium.org6f015bd2011-11-29 07:13:54 +0900339 }
340};
341
tzik103f4732017-07-31 19:41:54 +0900342// Extracts necessary type info from Functor and BoundArgs.
343// Used to implement MakeUnboundRunType, BindOnce and BindRepeating.
tzikfa6c9852016-06-28 21:22:21 +0900344template <typename Functor, typename... BoundArgs>
tzik103f4732017-07-31 19:41:54 +0900345struct BindTypeHelper {
346 static constexpr size_t num_bounds = sizeof...(BoundArgs);
347 using FunctorTraits = MakeFunctorTraits<Functor>;
348
349 // Example:
350 // When Functor is `double (Foo::*)(int, const std::string&)`, and BoundArgs
351 // is a template pack of `Foo*` and `int16_t`:
352 // - RunType is `double(Foo*, int, const std::string&)`,
353 // - ReturnType is `double`,
354 // - RunParamsList is `TypeList<Foo*, int, const std::string&>`,
355 // - BoundParamsList is `TypeList<Foo*, int>`,
356 // - UnboundParamsList is `TypeList<const std::string&>`,
357 // - BoundArgsList is `TypeList<Foo*, int16_t>`,
358 // - UnboundRunType is `double(const std::string&)`.
359 using RunType = typename FunctorTraits::RunType;
tzikfa6c9852016-06-28 21:22:21 +0900360 using ReturnType = ExtractReturnType<RunType>;
tzik103f4732017-07-31 19:41:54 +0900361
362 using RunParamsList = ExtractArgs<RunType>;
363 using BoundParamsList = TakeTypeListItem<num_bounds, RunParamsList>;
364 using UnboundParamsList = DropTypeListItem<num_bounds, RunParamsList>;
365
366 using BoundArgsList = TypeList<BoundArgs...>;
367
368 using UnboundRunType = MakeFunctionType<ReturnType, UnboundParamsList>;
tzikfa6c9852016-06-28 21:22:21 +0900369};
tzik103f4732017-07-31 19:41:54 +0900370
tzik31d3fae2016-07-08 18:42:38 +0900371template <typename Functor>
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900372std::enable_if_t<FunctorTraits<Functor>::is_nullable, bool> IsNull(
373 const Functor& functor) {
tzik31d3fae2016-07-08 18:42:38 +0900374 return !functor;
375}
376
377template <typename Functor>
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900378std::enable_if_t<!FunctorTraits<Functor>::is_nullable, bool> IsNull(
379 const Functor&) {
tzik31d3fae2016-07-08 18:42:38 +0900380 return false;
381}
tzikfa6c9852016-06-28 21:22:21 +0900382
tzike6e61952016-11-26 00:56:36 +0900383// Used by ApplyCancellationTraits below.
384template <typename Functor, typename BoundArgsTuple, size_t... indices>
385bool ApplyCancellationTraitsImpl(const Functor& functor,
386 const BoundArgsTuple& bound_args,
Jeremy Roman773e7f22017-08-17 00:55:20 +0900387 std::index_sequence<indices...>) {
tzike6e61952016-11-26 00:56:36 +0900388 return CallbackCancellationTraits<Functor, BoundArgsTuple>::IsCancelled(
tzik3c147c42017-04-06 06:45:03 +0900389 functor, std::get<indices>(bound_args)...);
tzike6e61952016-11-26 00:56:36 +0900390}
tzik058872d2016-09-08 19:58:53 +0900391
tzike6e61952016-11-26 00:56:36 +0900392// Relays |base| to corresponding CallbackCancellationTraits<>::Run(). Returns
393// true if the callback |base| represents is canceled.
394template <typename BindStateType>
395bool ApplyCancellationTraits(const BindStateBase* base) {
396 const BindStateType* storage = static_cast<const BindStateType*>(base);
397 static constexpr size_t num_bound_args =
398 std::tuple_size<decltype(storage->bound_args_)>::value;
Jeremy Roman773e7f22017-08-17 00:55:20 +0900399 return ApplyCancellationTraitsImpl(
400 storage->functor_, storage->bound_args_,
401 std::make_index_sequence<num_bound_args>());
tzik058872d2016-09-08 19:58:53 +0900402};
403
dchengb78a84f2016-09-24 14:05:57 +0900404// Template helpers to detect using Bind() on a base::Callback without any
405// additional arguments. In that case, the original base::Callback object should
406// just be directly used.
407template <typename Functor, typename... BoundArgs>
408struct BindingCallbackWithNoArgs {
409 static constexpr bool value = false;
410};
411
412template <typename Signature,
413 typename... BoundArgs,
414 CopyMode copy_mode,
415 RepeatMode repeat_mode>
416struct BindingCallbackWithNoArgs<Callback<Signature, copy_mode, repeat_mode>,
417 BoundArgs...> {
418 static constexpr bool value = sizeof...(BoundArgs) == 0;
419};
420
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900421// BindState<>
422//
tzik9f27e1f2016-07-01 14:54:12 +0900423// This stores all the state passed into Bind().
424template <typename Functor, typename... BoundArgs>
425struct BindState final : BindStateBase {
tzik1d2f3632016-09-14 16:15:00 +0900426 using IsCancellable = std::integral_constant<
tzike6e61952016-11-26 00:56:36 +0900427 bool,
428 CallbackCancellationTraits<Functor,
429 std::tuple<BoundArgs...>>::is_cancellable>;
tzik1d2f3632016-09-14 16:15:00 +0900430
tzikb4ec92d2016-07-08 23:14:01 +0900431 template <typename ForwardFunctor, typename... ForwardBoundArgs>
tzikd0473e62016-09-08 14:45:38 +0900432 explicit BindState(BindStateBase::InvokeFuncStorage invoke_func,
433 ForwardFunctor&& functor,
434 ForwardBoundArgs&&... bound_args)
tzike6e61952016-11-26 00:56:36 +0900435 // IsCancellable is std::false_type if
436 // CallbackCancellationTraits<>::IsCancelled returns always false.
437 // Otherwise, it's std::true_type.
tzik1d2f3632016-09-14 16:15:00 +0900438 : BindState(IsCancellable{},
439 invoke_func,
440 std::forward<ForwardFunctor>(functor),
dchengb78a84f2016-09-24 14:05:57 +0900441 std::forward<ForwardBoundArgs>(bound_args)...) {
442 static_assert(!BindingCallbackWithNoArgs<Functor, BoundArgs...>::value,
443 "Attempting to bind a base::Callback with no additional "
444 "arguments: save a heap allocation and use the original "
445 "base::Callback object");
446 }
tzik1d2f3632016-09-14 16:15:00 +0900447
448 Functor functor_;
449 std::tuple<BoundArgs...> bound_args_;
450
451 private:
452 template <typename ForwardFunctor, typename... ForwardBoundArgs>
453 explicit BindState(std::true_type,
454 BindStateBase::InvokeFuncStorage invoke_func,
455 ForwardFunctor&& functor,
456 ForwardBoundArgs&&... bound_args)
tzike6e61952016-11-26 00:56:36 +0900457 : BindStateBase(invoke_func,
458 &Destroy,
459 &ApplyCancellationTraits<BindState>),
tzike467aa42016-08-31 20:50:41 +0900460 functor_(std::forward<ForwardFunctor>(functor)),
tzik9f27e1f2016-07-01 14:54:12 +0900461 bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
tzik31d3fae2016-07-08 18:42:38 +0900462 DCHECK(!IsNull(functor_));
tzik9f27e1f2016-07-01 14:54:12 +0900463 }
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900464
tzik1d2f3632016-09-14 16:15:00 +0900465 template <typename ForwardFunctor, typename... ForwardBoundArgs>
466 explicit BindState(std::false_type,
467 BindStateBase::InvokeFuncStorage invoke_func,
468 ForwardFunctor&& functor,
469 ForwardBoundArgs&&... bound_args)
470 : BindStateBase(invoke_func, &Destroy),
471 functor_(std::forward<ForwardFunctor>(functor)),
472 bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
473 DCHECK(!IsNull(functor_));
474 }
dmichael2f7bc202014-12-19 07:30:11 +0900475
tapted9cef4212015-05-14 17:03:32 +0900476 ~BindState() {}
477
tzikfecd1862016-09-21 17:06:54 +0900478 static void Destroy(const BindStateBase* self) {
479 delete static_cast<const BindState*>(self);
tapted9cef4212015-05-14 17:03:32 +0900480 }
ajwong@chromium.org6f015bd2011-11-29 07:13:54 +0900481};
482
tzik9f27e1f2016-07-01 14:54:12 +0900483// Used to implement MakeBindStateType.
484template <bool is_method, typename Functor, typename... BoundArgs>
485struct MakeBindStateTypeImpl;
486
487template <typename Functor, typename... BoundArgs>
488struct MakeBindStateTypeImpl<false, Functor, BoundArgs...> {
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900489 static_assert(!HasRefCountedTypeAsRawPtr<std::decay_t<BoundArgs>...>::value,
tzik9f27e1f2016-07-01 14:54:12 +0900490 "A parameter is a refcounted type and needs scoped_refptr.");
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900491 using Type = BindState<std::decay_t<Functor>, std::decay_t<BoundArgs>...>;
tzik9f27e1f2016-07-01 14:54:12 +0900492};
493
494template <typename Functor>
495struct MakeBindStateTypeImpl<true, Functor> {
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900496 using Type = BindState<std::decay_t<Functor>>;
tzik9f27e1f2016-07-01 14:54:12 +0900497};
498
499template <typename Functor, typename Receiver, typename... BoundArgs>
500struct MakeBindStateTypeImpl<true, Functor, Receiver, BoundArgs...> {
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900501 static_assert(!std::is_array<std::remove_reference_t<Receiver>>::value,
502 "First bound argument to a method cannot be an array.");
503 static_assert(!HasRefCountedTypeAsRawPtr<std::decay_t<BoundArgs>...>::value,
tzik9f27e1f2016-07-01 14:54:12 +0900504 "A parameter is a refcounted type and needs scoped_refptr.");
505
506 private:
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900507 using DecayedReceiver = std::decay_t<Receiver>;
tzik9f27e1f2016-07-01 14:54:12 +0900508
509 public:
510 using Type = BindState<
Jeremy Roman8b4e2f32017-08-17 07:20:53 +0900511 std::decay_t<Functor>,
512 std::conditional_t<std::is_pointer<DecayedReceiver>::value,
513 scoped_refptr<std::remove_pointer_t<DecayedReceiver>>,
514 DecayedReceiver>,
515 std::decay_t<BoundArgs>...>;
tzik9f27e1f2016-07-01 14:54:12 +0900516};
517
518template <typename Functor, typename... BoundArgs>
tzik103f4732017-07-31 19:41:54 +0900519using MakeBindStateType =
520 typename MakeBindStateTypeImpl<MakeFunctorTraits<Functor>::is_method,
521 Functor,
522 BoundArgs...>::Type;
tzik9f27e1f2016-07-01 14:54:12 +0900523
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900524} // namespace internal
tzikfa6c9852016-06-28 21:22:21 +0900525
526// Returns a RunType of bound functor.
527// E.g. MakeUnboundRunType<R(A, B, C), A, B> is evaluated to R(C).
528template <typename Functor, typename... BoundArgs>
529using MakeUnboundRunType =
tzik103f4732017-07-31 19:41:54 +0900530 typename internal::BindTypeHelper<Functor, BoundArgs...>::UnboundRunType;
tzikfa6c9852016-06-28 21:22:21 +0900531
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900532} // namespace base
533
534#endif // BASE_BIND_INTERNAL_H_