blob: 9d5720fa48942e5b1d9d1974f5c407c2f2c4c28a [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]b38d3572011-02-15 01:27:3813#include "base/bind_helpers.h"
[email protected]59eff912011-02-18 23:29:3114#include "base/callback_internal.h"
[email protected]8217d4542011-10-01 06:31:4115#include "base/memory/raw_scoped_refptr_mismatch_checker.h"
[email protected]93540582011-05-16 22:35:1416#include "base/memory/weak_ptr.h"
[email protected]b38d3572011-02-15 01:27:3817#include "base/template_util.h"
[email protected]054ac7542011-02-27 01:25:5918#include "build/build_config.h"
19
[email protected]b38d3572011-02-15 01:27:3820namespace base {
21namespace internal {
22
[email protected]24292642012-07-12 20:06:4023// See base/callback.h for user documentation.
24//
25//
[email protected]7296f2762011-11-21 19:23:4426// CONCEPTS:
tzik99de02b2016-07-01 05:54:1227// 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.
[email protected]7296f2762011-11-21 19:23:4430// RunType -- A function type (as opposed to function _pointer_ type) for
tzik99de02b2016-07-01 05:54:1231// a Callback<>::Run(). Usually just a convenience typedef.
tzikce3ecf82015-12-15 06:41:4932// (Bound)Args -- A set of types that stores the arguments.
[email protected]b38d3572011-02-15 01:27:3833//
[email protected]7296f2762011-11-21 19:23:4434// Types:
[email protected]7296f2762011-11-21 19:23:4435// ForceVoidReturn<> -- Helper class for translating function signatures to
36// equivalent forms with a "void" return type.
tzik99de02b2016-07-01 05:54:1237// FunctorTraits<> -- Type traits used to determine the correct RunType and
38// invocation manner for a Functor. This is where function
[email protected]7296f2762011-11-21 19:23:4439// signature adapters are applied.
tzik99de02b2016-07-01 05:54:1240// InvokeHelper<> -- Take a Functor + arguments and actully invokes it.
tzik8ce65702015-02-05 19:11:2641// Handle the differing syntaxes needed for WeakPtr<>
tzik99de02b2016-07-01 05:54:1242// support. This is separate from Invoker to avoid creating
43// multiple version of Invoker<>.
44// Invoker<> -- Unwraps the curried parameters and executes the Functor.
[email protected]7296f2762011-11-21 19:23:4445// BindState<> -- Stores the curried parameters, and is the main entry point
tzik99de02b2016-07-01 05:54:1246// into the Bind() system.
[email protected]4346ef912011-02-19 00:52:1547
tzikc1db72652016-07-08 09:42:3848template <typename Callable,
49 typename Signature = decltype(&Callable::operator())>
50struct ExtractCallableRunTypeImpl;
51
52template <typename Callable, typename R, typename... Args>
tzikf98654b2017-12-02 03:28:5853struct 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> {
tzikc1db72652016-07-08 09:42:3859 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
tzikf98654b2017-12-02 03:28:5872// IsCallableObject<Functor> is std::true_type if |Functor| has operator().
73// Otherwise, it's std::false_type.
tzikc1db72652016-07-08 09:42:3874// Example:
tzikf98654b2017-12-02 03:28:5875// IsCallableObject<void(*)()>::value is false.
tzikc1db72652016-07-08 09:42:3876//
77// struct Foo {};
tzikf98654b2017-12-02 03:28:5878// IsCallableObject<void(Foo::*)()>::value is false.
tzikc1db72652016-07-08 09:42:3879//
80// int i = 0;
tzikf98654b2017-12-02 03:28:5881// auto f = [i]() {};
82// IsCallableObject<decltype(f)>::value is false.
tzikc1db72652016-07-08 09:42:3883template <typename Functor, typename SFINAE = void>
tzikf98654b2017-12-02 03:28:5884struct IsCallableObject : std::false_type {};
tzikc1db72652016-07-08 09:42:3885
86template <typename Callable>
tzikf98654b2017-12-02 03:28:5887struct IsCallableObject<Callable, void_t<decltype(&Callable::operator())>>
88 : std::true_type {};
tzikc1db72652016-07-08 09:42:3889
tzik401dd3672014-11-26 07:54:5890// 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>
tzik403cb6c2016-03-10 07:17:2595struct HasRefCountedTypeAsRawPtr : std::false_type {};
tzik401dd3672014-11-26 07:54:5896
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 Roman35a317432017-08-16 22:20:53102 : std::conditional_t<NeedsScopedRefptrButGetsRawPtr<T>::value,
103 std::true_type,
104 HasRefCountedTypeAsRawPtr<Args...>> {};
tzik401dd3672014-11-26 07:54:58105
[email protected]7296f2762011-11-21 19:23:44106// ForceVoidReturn<>
107//
108// Set of templates that support forcing the function return type to void.
109template <typename Sig>
110struct ForceVoidReturn;
111
tzikc82149922014-11-20 10:09:45112template <typename R, typename... Args>
113struct ForceVoidReturn<R(Args...)> {
tzik99de02b2016-07-01 05:54:12114 using RunType = void(Args...);
[email protected]fccef1552011-11-28 22:13:54115};
116
[email protected]7296f2762011-11-21 19:23:44117// FunctorTraits<>
118//
119// See description at top of file.
tzik6c92eab2016-11-25 15:56:36120template <typename Functor, typename SFINAE>
tzik99de02b2016-07-01 05:54:12121struct FunctorTraits;
122
tzikf98654b2017-12-02 03:28:58123// For empty callable types.
tzikc1db72652016-07-08 09:42:38124// This specialization is intended to allow binding captureless lambdas by
tzikf98654b2017-12-02 03:28:58125// 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// };
tzikc1db72652016-07-08 09:42:38142template <typename Functor>
Jeremy Roman35a317432017-08-16 22:20:53143struct FunctorTraits<Functor,
tzikf98654b2017-12-02 03:28:58144 std::enable_if_t<IsCallableObject<Functor>::value &&
145 std::is_empty<Functor>::value>> {
tzikc1db72652016-07-08 09:42:38146 using RunType = ExtractCallableRunType<Functor>;
147 static constexpr bool is_method = false;
148 static constexpr bool is_nullable = false;
149
tzikf98654b2017-12-02 03:28:58150 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)...);
tzikc1db72652016-07-08 09:42:38154 }
155};
156
tzik99de02b2016-07-01 05:54:12157// For functions.
158template <typename R, typename... Args>
159struct FunctorTraits<R (*)(Args...)> {
160 using RunType = R(Args...);
161 static constexpr bool is_method = false;
tzikc1db72652016-07-08 09:42:38162 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12163
164 template <typename... RunArgs>
165 static R Invoke(R (*function)(Args...), RunArgs&&... args) {
166 return function(std::forward<RunArgs>(args)...);
167 }
[email protected]7296f2762011-11-21 19:23:44168};
169
tzik99de02b2016-07-01 05:54:12170#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;
tzikc1db72652016-07-08 09:42:38177 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12178
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;
tzikc1db72652016-07-08 09:42:38190 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12191
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;
tzikc1db72652016-07-08 09:42:38205 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12206
207 template <typename ReceiverPtr, typename... RunArgs>
208 static R Invoke(R (Receiver::*method)(Args...),
209 ReceiverPtr&& receiver_ptr,
210 RunArgs&&... args) {
tzik75851f42017-06-14 06:57:01211 return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
tzik99de02b2016-07-01 05:54:12212 }
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;
tzikc1db72652016-07-08 09:42:38220 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12221
222 template <typename ReceiverPtr, typename... RunArgs>
223 static R Invoke(R (Receiver::*method)(Args...) const,
224 ReceiverPtr&& receiver_ptr,
225 RunArgs&&... args) {
tzik75851f42017-06-14 06:57:01226 return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
tzik99de02b2016-07-01 05:54:12227 }
228};
229
230// For IgnoreResults.
[email protected]7296f2762011-11-21 19:23:44231template <typename T>
tzik99de02b2016-07-01 05:54:12232struct FunctorTraits<IgnoreResultHelper<T>> : FunctorTraits<T> {
tzik3bc7779b2015-12-19 09:18:46233 using RunType =
tzik99de02b2016-07-01 05:54:12234 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) {
tzikff54a5b152016-08-31 11:50:41239 FunctorTraits<T>::Invoke(
240 std::forward<IgnoreResultType>(ignore_result_helper).functor_,
241 std::forward<RunArgs>(args)...);
tzik99de02b2016-07-01 05:54:12242 }
[email protected]7296f2762011-11-21 19:23:44243};
244
tzikd4bb5b7d2017-08-28 19:08:52245// 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...)>> {
tzik99de02b2016-07-01 05:54:12263 using RunType = R(Args...);
264 static constexpr bool is_method = false;
tzikc1db72652016-07-08 09:42:38265 static constexpr bool is_nullable = true;
tzik99de02b2016-07-01 05:54:12266
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 }
[email protected]7296f2762011-11-21 19:23:44273};
274
tzikae4202e2017-07-31 10:41:54275template <typename Functor>
Jeremy Roman35a317432017-08-16 22:20:53276using MakeFunctorTraits = FunctorTraits<std::decay_t<Functor>>;
tzikae4202e2017-07-31 10:41:54277
[email protected]7296f2762011-11-21 19:23:44278// InvokeHelper<>
279//
tzik99de02b2016-07-01 05:54:12280// There are 2 logical InvokeHelper<> specializations: normal, WeakCalls.
[email protected]7296f2762011-11-21 19:23:44281//
282// The normal type just calls the underlying runnable.
283//
tzik99de02b2016-07-01 05:54:12284// WeakCalls need special syntax that is applied to the first argument to check
285// if they should no-op themselves.
tzikee248722016-06-01 08:22:51286template <bool is_weak_call, typename ReturnType>
[email protected]7296f2762011-11-21 19:23:44287struct InvokeHelper;
288
tzikee248722016-06-01 08:22:51289template <typename ReturnType>
290struct InvokeHelper<false, ReturnType> {
tzik99de02b2016-07-01 05:54:12291 template <typename Functor, typename... RunArgs>
292 static inline ReturnType MakeItSo(Functor&& functor, RunArgs&&... args) {
tzikae4202e2017-07-31 10:41:54293 using Traits = MakeFunctorTraits<Functor>;
tzik99de02b2016-07-01 05:54:12294 return Traits::Invoke(std::forward<Functor>(functor),
295 std::forward<RunArgs>(args)...);
[email protected]7296f2762011-11-21 19:23:44296 }
297};
298
tzikee248722016-06-01 08:22:51299template <typename ReturnType>
300struct InvokeHelper<true, ReturnType> {
[email protected]7296f2762011-11-21 19:23:44301 // 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.
tzik403cb6c2016-03-10 07:17:25304 static_assert(std::is_void<ReturnType>::value,
avi4ec0dff2015-11-24 14:26:24305 "weak_ptrs can only bind to methods without return values");
[email protected]c18b1052011-03-24 02:02:17306
tzik99de02b2016-07-01 05:54:12307 template <typename Functor, typename BoundWeakPtr, typename... RunArgs>
308 static inline void MakeItSo(Functor&& functor,
tzik33871d82016-07-14 12:12:06309 BoundWeakPtr&& weak_ptr,
tzik99de02b2016-07-01 05:54:12310 RunArgs&&... args) {
311 if (!weak_ptr)
312 return;
tzikae4202e2017-07-31 10:41:54313 using Traits = MakeFunctorTraits<Functor>;
tzik99de02b2016-07-01 05:54:12314 Traits::Invoke(std::forward<Functor>(functor),
315 std::forward<BoundWeakPtr>(weak_ptr),
316 std::forward<RunArgs>(args)...);
317 }
318};
[email protected]b38d3572011-02-15 01:27:38319
[email protected]7296f2762011-11-21 19:23:44320// Invoker<>
321//
322// See description at the top of the file.
tzikcaf1d84b2016-06-28 12:22:21323template <typename StorageType, typename UnboundRunType>
[email protected]7296f2762011-11-21 19:23:44324struct Invoker;
325
tzikcaf1d84b2016-06-28 12:22:21326template <typename StorageType, typename R, typename... UnboundArgs>
327struct Invoker<StorageType, R(UnboundArgs...)> {
Vladislav Kuzkokov6d208e12017-11-08 21:31:08328 static R RunOnce(BindStateBase* base,
329 PassingTraitsType<UnboundArgs>... unbound_args) {
tzik27d1e312016-09-13 05:28:59330 // 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 Roman84956fa2017-08-16 15:55:20338 std::make_index_sequence<num_bound_args>(),
tzik27d1e312016-09-13 05:28:59339 std::forward<UnboundArgs>(unbound_args)...);
340 }
341
Vladislav Kuzkokov6d208e12017-11-08 21:31:08342 static R Run(BindStateBase* base,
343 PassingTraitsType<UnboundArgs>... unbound_args) {
[email protected]7296f2762011-11-21 19:23:44344 // 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.
tzikcaf1d84b2016-06-28 12:22:21347 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 Roman84956fa2017-08-16 15:55:20350 return RunImpl(storage->functor_, storage->bound_args_,
351 std::make_index_sequence<num_bound_args>(),
tzikcaf1d84b2016-06-28 12:22:21352 std::forward<UnboundArgs>(unbound_args)...);
353 }
354
tzik99de02b2016-07-01 05:54:12355 private:
356 template <typename Functor, typename BoundArgsTuple, size_t... indices>
357 static inline R RunImpl(Functor&& functor,
tzikcaf1d84b2016-06-28 12:22:21358 BoundArgsTuple&& bound,
Jeremy Roman84956fa2017-08-16 15:55:20359 std::index_sequence<indices...>,
tzikcaf1d84b2016-06-28 12:22:21360 UnboundArgs&&... unbound_args) {
tzikae4202e2017-07-31 10:41:54361 static constexpr bool is_method = MakeFunctorTraits<Functor>::is_method;
tzikcaf1d84b2016-06-28 12:22:21362
Jeremy Roman35a317432017-08-16 22:20:53363 using DecayedArgsTuple = std::decay_t<BoundArgsTuple>;
tzikcaf1d84b2016-06-28 12:22:21364 static constexpr bool is_weak_call =
365 IsWeakMethod<is_method,
Jeremy Roman35a317432017-08-16 22:20:53366 std::tuple_element_t<indices, DecayedArgsTuple>...>();
tzikcaf1d84b2016-06-28 12:22:21367
tzikee248722016-06-01 08:22:51368 return InvokeHelper<is_weak_call, R>::MakeItSo(
tzik99de02b2016-07-01 05:54:12369 std::forward<Functor>(functor),
tzikf7c47572017-04-05 21:45:03370 Unwrap(std::get<indices>(std::forward<BoundArgsTuple>(bound)))...,
tzika43eff02016-03-09 05:46:05371 std::forward<UnboundArgs>(unbound_args)...);
[email protected]fccef1552011-11-28 22:13:54372 }
373};
374
tzikae4202e2017-07-31 10:41:54375// Extracts necessary type info from Functor and BoundArgs.
376// Used to implement MakeUnboundRunType, BindOnce and BindRepeating.
tzikcaf1d84b2016-06-28 12:22:21377template <typename Functor, typename... BoundArgs>
tzikae4202e2017-07-31 10:41:54378struct 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;
tzikcaf1d84b2016-06-28 12:22:21393 using ReturnType = ExtractReturnType<RunType>;
tzikae4202e2017-07-31 10:41:54394
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>;
tzikcaf1d84b2016-06-28 12:22:21402};
tzikae4202e2017-07-31 10:41:54403
tzikc1db72652016-07-08 09:42:38404template <typename Functor>
Jeremy Roman35a317432017-08-16 22:20:53405std::enable_if_t<FunctorTraits<Functor>::is_nullable, bool> IsNull(
406 const Functor& functor) {
tzikc1db72652016-07-08 09:42:38407 return !functor;
408}
409
410template <typename Functor>
Jeremy Roman35a317432017-08-16 22:20:53411std::enable_if_t<!FunctorTraits<Functor>::is_nullable, bool> IsNull(
412 const Functor&) {
tzikc1db72652016-07-08 09:42:38413 return false;
414}
tzikcaf1d84b2016-06-28 12:22:21415
tzik6c92eab2016-11-25 15:56:36416// Used by ApplyCancellationTraits below.
417template <typename Functor, typename BoundArgsTuple, size_t... indices>
418bool ApplyCancellationTraitsImpl(const Functor& functor,
419 const BoundArgsTuple& bound_args,
Jeremy Roman84956fa2017-08-16 15:55:20420 std::index_sequence<indices...>) {
tzik6c92eab2016-11-25 15:56:36421 return CallbackCancellationTraits<Functor, BoundArgsTuple>::IsCancelled(
tzikf7c47572017-04-05 21:45:03422 functor, std::get<indices>(bound_args)...);
tzik6c92eab2016-11-25 15:56:36423}
tzik59aa6bb12016-09-08 10:58:53424
tzik6c92eab2016-11-25 15:56:36425// 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 Roman84956fa2017-08-16 15:55:20432 return ApplyCancellationTraitsImpl(
433 storage->functor_, storage->bound_args_,
434 std::make_index_sequence<num_bound_args>());
tzik59aa6bb12016-09-08 10:58:53435};
436
[email protected]7296f2762011-11-21 19:23:44437// BindState<>
438//
tzik99de02b2016-07-01 05:54:12439// This stores all the state passed into Bind().
440template <typename Functor, typename... BoundArgs>
441struct BindState final : BindStateBase {
tzik1fdcca32016-09-14 07:15:00442 using IsCancellable = std::integral_constant<
tzik6c92eab2016-11-25 15:56:36443 bool,
444 CallbackCancellationTraits<Functor,
445 std::tuple<BoundArgs...>>::is_cancellable>;
tzik1fdcca32016-09-14 07:15:00446
tzikbfe66122016-07-08 14:14:01447 template <typename ForwardFunctor, typename... ForwardBoundArgs>
tzik1886c272016-09-08 05:45:38448 explicit BindState(BindStateBase::InvokeFuncStorage invoke_func,
449 ForwardFunctor&& functor,
450 ForwardBoundArgs&&... bound_args)
tzik6c92eab2016-11-25 15:56:36451 // IsCancellable is std::false_type if
452 // CallbackCancellationTraits<>::IsCancelled returns always false.
453 // Otherwise, it's std::true_type.
tzik1fdcca32016-09-14 07:15:00454 : BindState(IsCancellable{},
455 invoke_func,
456 std::forward<ForwardFunctor>(functor),
tzikf98654b2017-12-02 03:28:58457 std::forward<ForwardBoundArgs>(bound_args)...) {}
tzik1fdcca32016-09-14 07:15:00458
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)
tzik6c92eab2016-11-25 15:56:36468 : BindStateBase(invoke_func,
469 &Destroy,
470 &ApplyCancellationTraits<BindState>),
tzikff54a5b152016-08-31 11:50:41471 functor_(std::forward<ForwardFunctor>(functor)),
tzik99de02b2016-07-01 05:54:12472 bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
tzikc1db72652016-07-08 09:42:38473 DCHECK(!IsNull(functor_));
tzik99de02b2016-07-01 05:54:12474 }
[email protected]7296f2762011-11-21 19:23:44475
tzik1fdcca32016-09-14 07:15:00476 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 }
dmichael7d09007e2014-12-18 22:30:11486
Chris Watkins091d6292017-12-13 04:25:58487 ~BindState() = default;
taptede7e804c2015-05-14 08:03:32488
tzik30e0c312016-09-21 08:06:54489 static void Destroy(const BindStateBase* self) {
490 delete static_cast<const BindState*>(self);
taptede7e804c2015-05-14 08:03:32491 }
[email protected]fccef1552011-11-28 22:13:54492};
493
tzik99de02b2016-07-01 05:54:12494// 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 Roman35a317432017-08-16 22:20:53500 static_assert(!HasRefCountedTypeAsRawPtr<std::decay_t<BoundArgs>...>::value,
tzik99de02b2016-07-01 05:54:12501 "A parameter is a refcounted type and needs scoped_refptr.");
Jeremy Roman35a317432017-08-16 22:20:53502 using Type = BindState<std::decay_t<Functor>, std::decay_t<BoundArgs>...>;
tzik99de02b2016-07-01 05:54:12503};
504
505template <typename Functor>
506struct MakeBindStateTypeImpl<true, Functor> {
Jeremy Roman35a317432017-08-16 22:20:53507 using Type = BindState<std::decay_t<Functor>>;
tzik99de02b2016-07-01 05:54:12508};
509
510template <typename Functor, typename Receiver, typename... BoundArgs>
511struct MakeBindStateTypeImpl<true, Functor, Receiver, BoundArgs...> {
Jeremy Roman35a317432017-08-16 22:20:53512 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,
tzik99de02b2016-07-01 05:54:12515 "A parameter is a refcounted type and needs scoped_refptr.");
516
517 private:
Jeremy Roman35a317432017-08-16 22:20:53518 using DecayedReceiver = std::decay_t<Receiver>;
tzik99de02b2016-07-01 05:54:12519
520 public:
521 using Type = BindState<
Jeremy Roman35a317432017-08-16 22:20:53522 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>...>;
tzik99de02b2016-07-01 05:54:12527};
528
529template <typename Functor, typename... BoundArgs>
tzikae4202e2017-07-31 10:41:54530using MakeBindStateType =
531 typename MakeBindStateTypeImpl<MakeFunctorTraits<Functor>::is_method,
532 Functor,
533 BoundArgs...>::Type;
tzik99de02b2016-07-01 05:54:12534
[email protected]b38d3572011-02-15 01:27:38535} // namespace internal
tzikcaf1d84b2016-06-28 12:22:21536
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 =
tzikae4202e2017-07-31 10:41:54541 typename internal::BindTypeHelper<Functor, BoundArgs...>::UnboundRunType;
tzikcaf1d84b2016-06-28 12:22:21542
[email protected]b38d3572011-02-15 01:27:38543} // namespace base
544
545#endif // BASE_BIND_INTERNAL_H_