blob: c8af87d5806cd2504208008b62908d44dedcb817 [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
tzikf09a3702016-06-03 16:25:20 +090010#include <tuple>
vmpstr495da402015-11-18 17:43:26 +090011#include <type_traits>
12
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"
tzik07e99402015-02-06 04:11:26 +090018#include "base/tuple.h"
ajwong@chromium.orgcb175342011-02-27 10:25:59 +090019#include "build/build_config.h"
20
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090021namespace base {
22namespace internal {
23
brettw@chromium.org11e3bfd2012-07-13 05:06:40 +090024// See base/callback.h for user documentation.
25//
26//
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +090027// CONCEPTS:
tzik9f27e1f2016-07-01 14:54:12 +090028// Functor -- A movable type representing something that should be called.
29// All function pointers and Callback<> are functors even if the
30// invocation syntax differs.
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +090031// RunType -- A function type (as opposed to function _pointer_ type) for
tzik9f27e1f2016-07-01 14:54:12 +090032// a Callback<>::Run(). Usually just a convenience typedef.
tzikb0632222015-12-15 15:41:49 +090033// (Bound)Args -- A set of types that stores the arguments.
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090034//
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +090035// Types:
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +090036// ForceVoidReturn<> -- Helper class for translating function signatures to
37// equivalent forms with a "void" return type.
tzik9f27e1f2016-07-01 14:54:12 +090038// FunctorTraits<> -- Type traits used to determine the correct RunType and
39// invocation manner for a Functor. This is where function
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +090040// signature adapters are applied.
tzik9f27e1f2016-07-01 14:54:12 +090041// InvokeHelper<> -- Take a Functor + arguments and actully invokes it.
tzik07e99402015-02-06 04:11:26 +090042// Handle the differing syntaxes needed for WeakPtr<>
tzik9f27e1f2016-07-01 14:54:12 +090043// support. This is separate from Invoker to avoid creating
44// multiple version of Invoker<>.
45// Invoker<> -- Unwraps the curried parameters and executes the Functor.
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +090046// BindState<> -- Stores the curried parameters, and is the main entry point
tzik9f27e1f2016-07-01 14:54:12 +090047// into the Bind() system.
ajwong@chromium.orge0648232011-02-19 09:52:15 +090048
tzik31d3fae2016-07-08 18:42:38 +090049template <typename...>
50struct make_void {
51 using type = void;
52};
53
54// A clone of C++17 std::void_t.
55// Unlike the original version, we need |make_void| as a helper struct to avoid
56// a C++14 defect.
57// ref: http://en.cppreference.com/w/cpp/types/void_t
58// ref: http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1558
59template <typename... Ts>
60using void_t = typename make_void<Ts...>::type;
61
62template <typename Callable,
63 typename Signature = decltype(&Callable::operator())>
64struct ExtractCallableRunTypeImpl;
65
66template <typename Callable, typename R, typename... Args>
67struct ExtractCallableRunTypeImpl<Callable, R(Callable::*)(Args...) const> {
68 using Type = R(Args...);
69};
70
71// Evaluated to RunType of the given callable type.
72// Example:
73// auto f = [](int, char*) { return 0.1; };
74// ExtractCallableRunType<decltype(f)>
75// is evaluated to
76// double(int, char*);
77template <typename Callable>
78using ExtractCallableRunType =
79 typename ExtractCallableRunTypeImpl<Callable>::Type;
80
81// IsConvertibleToRunType<Functor> is std::true_type if |Functor| has operator()
82// and convertible to the corresponding function pointer. Otherwise, it's
83// std::false_type.
84// Example:
85// IsConvertibleToRunType<void(*)()>::value is false.
86//
87// struct Foo {};
88// IsConvertibleToRunType<void(Foo::*)()>::value is false.
89//
90// auto f = []() {};
91// IsConvertibleToRunType<decltype(f)>::value is true.
92//
93// int i = 0;
94// auto g = [i]() {};
95// IsConvertibleToRunType<decltype(g)>::value is false.
96template <typename Functor, typename SFINAE = void>
97struct IsConvertibleToRunType : std::false_type {};
98
99template <typename Callable>
100struct IsConvertibleToRunType<Callable, void_t<decltype(&Callable::operator())>>
101 : std::is_convertible<Callable, ExtractCallableRunType<Callable>*> {};
102
tzik8df08a52014-11-26 16:54:58 +0900103// HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw
104// pointer to a RefCounted type.
105// Implementation note: This non-specialized case handles zero-arity case only.
106// Non-zero-arity cases should be handled by the specialization below.
107template <typename... Args>
tzik56bd7652016-03-10 16:17:25 +0900108struct HasRefCountedTypeAsRawPtr : std::false_type {};
tzik8df08a52014-11-26 16:54:58 +0900109
110// Implementation note: Select true_type if the first parameter is a raw pointer
111// to a RefCounted type. Otherwise, skip the first parameter and check rest of
112// parameters recursively.
113template <typename T, typename... Args>
114struct HasRefCountedTypeAsRawPtr<T, Args...>
vmpstr495da402015-11-18 17:43:26 +0900115 : std::conditional<NeedsScopedRefptrButGetsRawPtr<T>::value,
tzik56bd7652016-03-10 16:17:25 +0900116 std::true_type,
vmpstr495da402015-11-18 17:43:26 +0900117 HasRefCountedTypeAsRawPtr<Args...>>::type {};
tzik8df08a52014-11-26 16:54:58 +0900118
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900119// ForceVoidReturn<>
120//
121// Set of templates that support forcing the function return type to void.
122template <typename Sig>
123struct ForceVoidReturn;
124
tzik012481a2014-11-20 19:09:45 +0900125template <typename R, typename... Args>
126struct ForceVoidReturn<R(Args...)> {
tzik9f27e1f2016-07-01 14:54:12 +0900127 using RunType = void(Args...);
ajwong@chromium.org6f015bd2011-11-29 07:13:54 +0900128};
129
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900130// FunctorTraits<>
131//
132// See description at top of file.
tzike6e61952016-11-26 00:56:36 +0900133template <typename Functor, typename SFINAE>
tzik9f27e1f2016-07-01 14:54:12 +0900134struct FunctorTraits;
135
tzik31d3fae2016-07-08 18:42:38 +0900136// For a callable type that is convertible to the corresponding function type.
137// This specialization is intended to allow binding captureless lambdas by
138// base::Bind(), based on the fact that captureless lambdas can be convertible
139// to the function type while capturing lambdas can't.
140template <typename Functor>
141struct FunctorTraits<
142 Functor,
143 typename std::enable_if<IsConvertibleToRunType<Functor>::value>::type> {
144 using RunType = ExtractCallableRunType<Functor>;
145 static constexpr bool is_method = false;
146 static constexpr bool is_nullable = false;
147
148 template <typename... RunArgs>
149 static ExtractReturnType<RunType>
150 Invoke(const Functor& functor, RunArgs&&... args) {
151 return functor(std::forward<RunArgs>(args)...);
152 }
153};
154
tzik9f27e1f2016-07-01 14:54:12 +0900155// For functions.
156template <typename R, typename... Args>
157struct FunctorTraits<R (*)(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 (*function)(Args...), RunArgs&&... args) {
164 return function(std::forward<RunArgs>(args)...);
165 }
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900166};
167
tzik9f27e1f2016-07-01 14:54:12 +0900168#if defined(OS_WIN) && !defined(ARCH_CPU_X86_64)
169
170// For functions.
171template <typename R, typename... Args>
172struct FunctorTraits<R(__stdcall*)(Args...)> {
173 using RunType = R(Args...);
174 static constexpr bool is_method = false;
tzik31d3fae2016-07-08 18:42:38 +0900175 static constexpr bool is_nullable = true;
tzik9f27e1f2016-07-01 14:54:12 +0900176
177 template <typename... RunArgs>
178 static R Invoke(R(__stdcall* function)(Args...), RunArgs&&... args) {
179 return function(std::forward<RunArgs>(args)...);
180 }
181};
182
183// For functions.
184template <typename R, typename... Args>
185struct FunctorTraits<R(__fastcall*)(Args...)> {
186 using RunType = R(Args...);
187 static constexpr bool is_method = false;
tzik31d3fae2016-07-08 18:42:38 +0900188 static constexpr bool is_nullable = true;
tzik9f27e1f2016-07-01 14:54:12 +0900189
190 template <typename... RunArgs>
191 static R Invoke(R(__fastcall* function)(Args...), RunArgs&&... args) {
192 return function(std::forward<RunArgs>(args)...);
193 }
194};
195
196#endif // defined(OS_WIN) && !defined(ARCH_CPU_X86_64)
197
198// For methods.
199template <typename R, typename Receiver, typename... Args>
200struct FunctorTraits<R (Receiver::*)(Args...)> {
201 using RunType = R(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...),
207 ReceiverPtr&& receiver_ptr,
208 RunArgs&&... args) {
209 // Clang skips CV qualifier check on a method pointer invocation when the
210 // receiver is a subclass. Store the receiver into a const reference to
211 // T to ensure the CV check works.
212 // https://llvm.org/bugs/show_bug.cgi?id=27037
213 Receiver& receiver = *receiver_ptr;
214 return (receiver.*method)(std::forward<RunArgs>(args)...);
215 }
216};
217
218// For const methods.
219template <typename R, typename Receiver, typename... Args>
220struct FunctorTraits<R (Receiver::*)(Args...) const> {
221 using RunType = R(const Receiver*, Args...);
222 static constexpr bool is_method = true;
tzik31d3fae2016-07-08 18:42:38 +0900223 static constexpr bool is_nullable = true;
tzik9f27e1f2016-07-01 14:54:12 +0900224
225 template <typename ReceiverPtr, typename... RunArgs>
226 static R Invoke(R (Receiver::*method)(Args...) const,
227 ReceiverPtr&& receiver_ptr,
228 RunArgs&&... args) {
229 // Clang skips CV qualifier check on a method pointer invocation when the
230 // receiver is a subclass. Store the receiver into a const reference to
231 // T to ensure the CV check works.
232 // https://llvm.org/bugs/show_bug.cgi?id=27037
233 const Receiver& receiver = *receiver_ptr;
234 return (receiver.*method)(std::forward<RunArgs>(args)...);
235 }
236};
237
238// For IgnoreResults.
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900239template <typename T>
tzik9f27e1f2016-07-01 14:54:12 +0900240struct FunctorTraits<IgnoreResultHelper<T>> : FunctorTraits<T> {
tzik260fab52015-12-19 18:18:46 +0900241 using RunType =
tzik9f27e1f2016-07-01 14:54:12 +0900242 typename ForceVoidReturn<typename FunctorTraits<T>::RunType>::RunType;
243
244 template <typename IgnoreResultType, typename... RunArgs>
245 static void Invoke(IgnoreResultType&& ignore_result_helper,
246 RunArgs&&... args) {
tzike467aa42016-08-31 20:50:41 +0900247 FunctorTraits<T>::Invoke(
248 std::forward<IgnoreResultType>(ignore_result_helper).functor_,
249 std::forward<RunArgs>(args)...);
tzik9f27e1f2016-07-01 14:54:12 +0900250 }
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900251};
252
tzik9f27e1f2016-07-01 14:54:12 +0900253// For Callbacks.
tzikc60a8122016-09-13 14:28:59 +0900254template <typename R, typename... Args,
255 CopyMode copy_mode, RepeatMode repeat_mode>
256struct FunctorTraits<Callback<R(Args...), copy_mode, repeat_mode>> {
tzik9f27e1f2016-07-01 14:54:12 +0900257 using RunType = R(Args...);
258 static constexpr bool is_method = false;
tzik31d3fae2016-07-08 18:42:38 +0900259 static constexpr bool is_nullable = true;
tzik9f27e1f2016-07-01 14:54:12 +0900260
261 template <typename CallbackType, typename... RunArgs>
262 static R Invoke(CallbackType&& callback, RunArgs&&... args) {
263 DCHECK(!callback.is_null());
264 return std::forward<CallbackType>(callback).Run(
265 std::forward<RunArgs>(args)...);
266 }
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900267};
268
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900269// InvokeHelper<>
270//
tzik9f27e1f2016-07-01 14:54:12 +0900271// There are 2 logical InvokeHelper<> specializations: normal, WeakCalls.
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900272//
273// The normal type just calls the underlying runnable.
274//
tzik9f27e1f2016-07-01 14:54:12 +0900275// WeakCalls need special syntax that is applied to the first argument to check
276// if they should no-op themselves.
tzike1ad6f62016-06-01 17:22:51 +0900277template <bool is_weak_call, typename ReturnType>
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900278struct InvokeHelper;
279
tzike1ad6f62016-06-01 17:22:51 +0900280template <typename ReturnType>
281struct InvokeHelper<false, ReturnType> {
tzik9f27e1f2016-07-01 14:54:12 +0900282 template <typename Functor, typename... RunArgs>
283 static inline ReturnType MakeItSo(Functor&& functor, RunArgs&&... args) {
284 using Traits = FunctorTraits<typename std::decay<Functor>::type>;
285 return Traits::Invoke(std::forward<Functor>(functor),
286 std::forward<RunArgs>(args)...);
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900287 }
288};
289
tzike1ad6f62016-06-01 17:22:51 +0900290template <typename ReturnType>
291struct InvokeHelper<true, ReturnType> {
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900292 // WeakCalls are only supported for functions with a void return type.
293 // Otherwise, the function result would be undefined if the the WeakPtr<>
294 // is invalidated.
tzik56bd7652016-03-10 16:17:25 +0900295 static_assert(std::is_void<ReturnType>::value,
avi486c61f2015-11-24 23:26:24 +0900296 "weak_ptrs can only bind to methods without return values");
ajwong@chromium.orga7e74822011-03-24 11:02:17 +0900297
tzik9f27e1f2016-07-01 14:54:12 +0900298 template <typename Functor, typename BoundWeakPtr, typename... RunArgs>
299 static inline void MakeItSo(Functor&& functor,
tzik6bb5cb42016-07-14 21:12:06 +0900300 BoundWeakPtr&& weak_ptr,
tzik9f27e1f2016-07-01 14:54:12 +0900301 RunArgs&&... args) {
302 if (!weak_ptr)
303 return;
304 using Traits = FunctorTraits<typename std::decay<Functor>::type>;
305 Traits::Invoke(std::forward<Functor>(functor),
306 std::forward<BoundWeakPtr>(weak_ptr),
307 std::forward<RunArgs>(args)...);
308 }
309};
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900310
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900311// Invoker<>
312//
313// See description at the top of the file.
tzikfa6c9852016-06-28 21:22:21 +0900314template <typename StorageType, typename UnboundRunType>
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900315struct Invoker;
316
tzikfa6c9852016-06-28 21:22:21 +0900317template <typename StorageType, typename R, typename... UnboundArgs>
318struct Invoker<StorageType, R(UnboundArgs...)> {
tzikc60a8122016-09-13 14:28:59 +0900319 static R RunOnce(BindStateBase* base, UnboundArgs&&... unbound_args) {
320 // Local references to make debugger stepping easier. If in a debugger,
321 // you really want to warp ahead and step through the
322 // InvokeHelper<>::MakeItSo() call below.
323 StorageType* storage = static_cast<StorageType*>(base);
324 static constexpr size_t num_bound_args =
325 std::tuple_size<decltype(storage->bound_args_)>::value;
326 return RunImpl(std::move(storage->functor_),
327 std::move(storage->bound_args_),
328 MakeIndexSequence<num_bound_args>(),
329 std::forward<UnboundArgs>(unbound_args)...);
330 }
331
tzik0d4bab22016-03-09 14:46:05 +0900332 static R Run(BindStateBase* base, UnboundArgs&&... unbound_args) {
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900333 // Local references to make debugger stepping easier. If in a debugger,
334 // you really want to warp ahead and step through the
335 // InvokeHelper<>::MakeItSo() call below.
tzikfa6c9852016-06-28 21:22:21 +0900336 const StorageType* storage = static_cast<StorageType*>(base);
337 static constexpr size_t num_bound_args =
338 std::tuple_size<decltype(storage->bound_args_)>::value;
tzik9f27e1f2016-07-01 14:54:12 +0900339 return RunImpl(storage->functor_,
tzikfa6c9852016-06-28 21:22:21 +0900340 storage->bound_args_,
341 MakeIndexSequence<num_bound_args>(),
342 std::forward<UnboundArgs>(unbound_args)...);
343 }
344
tzik9f27e1f2016-07-01 14:54:12 +0900345 private:
346 template <typename Functor, typename BoundArgsTuple, size_t... indices>
347 static inline R RunImpl(Functor&& functor,
tzikfa6c9852016-06-28 21:22:21 +0900348 BoundArgsTuple&& bound,
349 IndexSequence<indices...>,
350 UnboundArgs&&... unbound_args) {
351 static constexpr bool is_method =
tzik9f27e1f2016-07-01 14:54:12 +0900352 FunctorTraits<typename std::decay<Functor>::type>::is_method;
tzikfa6c9852016-06-28 21:22:21 +0900353
354 using DecayedArgsTuple = typename std::decay<BoundArgsTuple>::type;
355 static constexpr bool is_weak_call =
356 IsWeakMethod<is_method,
357 typename std::tuple_element<
358 indices,
359 DecayedArgsTuple>::type...>::value;
360
tzike1ad6f62016-06-01 17:22:51 +0900361 return InvokeHelper<is_weak_call, R>::MakeItSo(
tzik9f27e1f2016-07-01 14:54:12 +0900362 std::forward<Functor>(functor),
tzik3c147c42017-04-06 06:45:03 +0900363 Unwrap(std::get<indices>(std::forward<BoundArgsTuple>(bound)))...,
tzik0d4bab22016-03-09 14:46:05 +0900364 std::forward<UnboundArgs>(unbound_args)...);
ajwong@chromium.org6f015bd2011-11-29 07:13:54 +0900365 }
366};
367
tzikfa6c9852016-06-28 21:22:21 +0900368// Used to implement MakeUnboundRunType.
369template <typename Functor, typename... BoundArgs>
370struct MakeUnboundRunTypeImpl {
tzik9f27e1f2016-07-01 14:54:12 +0900371 using RunType =
372 typename FunctorTraits<typename std::decay<Functor>::type>::RunType;
tzikfa6c9852016-06-28 21:22:21 +0900373 using ReturnType = ExtractReturnType<RunType>;
374 using Args = ExtractArgs<RunType>;
375 using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), Args>;
376 using Type = MakeFunctionType<ReturnType, UnboundArgs>;
377};
tzik31d3fae2016-07-08 18:42:38 +0900378template <typename Functor>
379typename std::enable_if<FunctorTraits<Functor>::is_nullable, bool>::type
380IsNull(const Functor& functor) {
381 return !functor;
382}
383
384template <typename Functor>
385typename std::enable_if<!FunctorTraits<Functor>::is_nullable, bool>::type
386IsNull(const Functor&) {
387 return false;
388}
tzikfa6c9852016-06-28 21:22:21 +0900389
tzike6e61952016-11-26 00:56:36 +0900390// Used by ApplyCancellationTraits below.
391template <typename Functor, typename BoundArgsTuple, size_t... indices>
392bool ApplyCancellationTraitsImpl(const Functor& functor,
393 const BoundArgsTuple& bound_args,
394 IndexSequence<indices...>) {
395 return CallbackCancellationTraits<Functor, BoundArgsTuple>::IsCancelled(
tzik3c147c42017-04-06 06:45:03 +0900396 functor, std::get<indices>(bound_args)...);
tzike6e61952016-11-26 00:56:36 +0900397}
tzik058872d2016-09-08 19:58:53 +0900398
tzike6e61952016-11-26 00:56:36 +0900399// Relays |base| to corresponding CallbackCancellationTraits<>::Run(). Returns
400// true if the callback |base| represents is canceled.
401template <typename BindStateType>
402bool ApplyCancellationTraits(const BindStateBase* base) {
403 const BindStateType* storage = static_cast<const BindStateType*>(base);
404 static constexpr size_t num_bound_args =
405 std::tuple_size<decltype(storage->bound_args_)>::value;
406 return ApplyCancellationTraitsImpl(storage->functor_, storage->bound_args_,
407 MakeIndexSequence<num_bound_args>());
tzik058872d2016-09-08 19:58:53 +0900408};
409
dchengb78a84f2016-09-24 14:05:57 +0900410// Template helpers to detect using Bind() on a base::Callback without any
411// additional arguments. In that case, the original base::Callback object should
412// just be directly used.
413template <typename Functor, typename... BoundArgs>
414struct BindingCallbackWithNoArgs {
415 static constexpr bool value = false;
416};
417
418template <typename Signature,
419 typename... BoundArgs,
420 CopyMode copy_mode,
421 RepeatMode repeat_mode>
422struct BindingCallbackWithNoArgs<Callback<Signature, copy_mode, repeat_mode>,
423 BoundArgs...> {
424 static constexpr bool value = sizeof...(BoundArgs) == 0;
425};
426
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900427// BindState<>
428//
tzik9f27e1f2016-07-01 14:54:12 +0900429// This stores all the state passed into Bind().
430template <typename Functor, typename... BoundArgs>
431struct BindState final : BindStateBase {
tzik1d2f3632016-09-14 16:15:00 +0900432 using IsCancellable = std::integral_constant<
tzike6e61952016-11-26 00:56:36 +0900433 bool,
434 CallbackCancellationTraits<Functor,
435 std::tuple<BoundArgs...>>::is_cancellable>;
tzik1d2f3632016-09-14 16:15:00 +0900436
tzikb4ec92d2016-07-08 23:14:01 +0900437 template <typename ForwardFunctor, typename... ForwardBoundArgs>
tzikd0473e62016-09-08 14:45:38 +0900438 explicit BindState(BindStateBase::InvokeFuncStorage invoke_func,
439 ForwardFunctor&& functor,
440 ForwardBoundArgs&&... bound_args)
tzike6e61952016-11-26 00:56:36 +0900441 // IsCancellable is std::false_type if
442 // CallbackCancellationTraits<>::IsCancelled returns always false.
443 // Otherwise, it's std::true_type.
tzik1d2f3632016-09-14 16:15:00 +0900444 : BindState(IsCancellable{},
445 invoke_func,
446 std::forward<ForwardFunctor>(functor),
dchengb78a84f2016-09-24 14:05:57 +0900447 std::forward<ForwardBoundArgs>(bound_args)...) {
448 static_assert(!BindingCallbackWithNoArgs<Functor, BoundArgs...>::value,
449 "Attempting to bind a base::Callback with no additional "
450 "arguments: save a heap allocation and use the original "
451 "base::Callback object");
452 }
tzik1d2f3632016-09-14 16:15:00 +0900453
454 Functor functor_;
455 std::tuple<BoundArgs...> bound_args_;
456
457 private:
458 template <typename ForwardFunctor, typename... ForwardBoundArgs>
459 explicit BindState(std::true_type,
460 BindStateBase::InvokeFuncStorage invoke_func,
461 ForwardFunctor&& functor,
462 ForwardBoundArgs&&... bound_args)
tzike6e61952016-11-26 00:56:36 +0900463 : BindStateBase(invoke_func,
464 &Destroy,
465 &ApplyCancellationTraits<BindState>),
tzike467aa42016-08-31 20:50:41 +0900466 functor_(std::forward<ForwardFunctor>(functor)),
tzik9f27e1f2016-07-01 14:54:12 +0900467 bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
tzik31d3fae2016-07-08 18:42:38 +0900468 DCHECK(!IsNull(functor_));
tzik9f27e1f2016-07-01 14:54:12 +0900469 }
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900470
tzik1d2f3632016-09-14 16:15:00 +0900471 template <typename ForwardFunctor, typename... ForwardBoundArgs>
472 explicit BindState(std::false_type,
473 BindStateBase::InvokeFuncStorage invoke_func,
474 ForwardFunctor&& functor,
475 ForwardBoundArgs&&... bound_args)
476 : BindStateBase(invoke_func, &Destroy),
477 functor_(std::forward<ForwardFunctor>(functor)),
478 bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
479 DCHECK(!IsNull(functor_));
480 }
dmichael2f7bc202014-12-19 07:30:11 +0900481
tapted9cef4212015-05-14 17:03:32 +0900482 ~BindState() {}
483
tzikfecd1862016-09-21 17:06:54 +0900484 static void Destroy(const BindStateBase* self) {
485 delete static_cast<const BindState*>(self);
tapted9cef4212015-05-14 17:03:32 +0900486 }
ajwong@chromium.org6f015bd2011-11-29 07:13:54 +0900487};
488
tzik9f27e1f2016-07-01 14:54:12 +0900489// Used to implement MakeBindStateType.
490template <bool is_method, typename Functor, typename... BoundArgs>
491struct MakeBindStateTypeImpl;
492
493template <typename Functor, typename... BoundArgs>
494struct MakeBindStateTypeImpl<false, Functor, BoundArgs...> {
495 static_assert(!HasRefCountedTypeAsRawPtr<BoundArgs...>::value,
496 "A parameter is a refcounted type and needs scoped_refptr.");
497 using Type = BindState<typename std::decay<Functor>::type,
498 typename std::decay<BoundArgs>::type...>;
499};
500
501template <typename Functor>
502struct MakeBindStateTypeImpl<true, Functor> {
503 using Type = BindState<typename std::decay<Functor>::type>;
504};
505
506template <typename Functor, typename Receiver, typename... BoundArgs>
507struct MakeBindStateTypeImpl<true, Functor, Receiver, BoundArgs...> {
508 static_assert(
509 !std::is_array<typename std::remove_reference<Receiver>::type>::value,
510 "First bound argument to a method cannot be an array.");
511 static_assert(!HasRefCountedTypeAsRawPtr<BoundArgs...>::value,
512 "A parameter is a refcounted type and needs scoped_refptr.");
513
514 private:
515 using DecayedReceiver = typename std::decay<Receiver>::type;
516
517 public:
518 using Type = BindState<
519 typename std::decay<Functor>::type,
520 typename std::conditional<
521 std::is_pointer<DecayedReceiver>::value,
522 scoped_refptr<typename std::remove_pointer<DecayedReceiver>::type>,
523 DecayedReceiver>::type,
524 typename std::decay<BoundArgs>::type...>;
525};
526
527template <typename Functor, typename... BoundArgs>
528using MakeBindStateType = typename MakeBindStateTypeImpl<
529 FunctorTraits<typename std::decay<Functor>::type>::is_method,
530 Functor,
531 BoundArgs...>::Type;
532
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900533} // namespace internal
tzikfa6c9852016-06-28 21:22:21 +0900534
535// Returns a RunType of bound functor.
536// E.g. MakeUnboundRunType<R(A, B, C), A, B> is evaluated to R(C).
537template <typename Functor, typename... BoundArgs>
538using MakeUnboundRunType =
539 typename internal::MakeUnboundRunTypeImpl<Functor, BoundArgs...>::Type;
540
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900541} // namespace base
542
543#endif // BASE_BIND_INTERNAL_H_