blob: e05321886223f8863693aba9e910408dc463696e [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
8#include "base/bind_helpers.h"
ajwong@chromium.orgfa0ff432011-02-19 08:29:31 +09009#include "base/callback_internal.h"
ajwong@chromium.org27e56852011-10-01 15:31:41 +090010#include "base/memory/raw_scoped_refptr_mismatch_checker.h"
ajwong@chromium.orgc711b822011-05-17 07:35:14 +090011#include "base/memory/weak_ptr.h"
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090012#include "base/template_util.h"
tzik07e99402015-02-06 04:11:26 +090013#include "base/tuple.h"
ajwong@chromium.orgcb175342011-02-27 10:25:59 +090014#include "build/build_config.h"
15
16#if defined(OS_WIN)
17#include "base/bind_internal_win.h"
18#endif
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090019
20namespace 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:
27// Runnable -- A type (really a type class) that has a single Run() method
28// and a RunType typedef that corresponds to the type of Run().
29// A Runnable can declare that it should treated like a method
30// call by including a typedef named IsMethod. The value of
31// this typedef is NOT inspected, only the existence. When a
32// Runnable declares itself a method, Bind() will enforce special
33// refcounting + WeakPtr handling semantics for the first
34// parameter which is expected to be an object.
35// Functor -- A copyable type representing something that should be called.
36// All function pointers, Callback<>, and Runnables are functors
37// even if the invocation syntax differs.
38// RunType -- A function type (as opposed to function _pointer_ type) for
39// a Run() function. Usually just a convenience typedef.
40// (Bound)ArgsType -- A function type that is being (ab)used to store the
41// types of set of arguments. The "return" type is always
42// void here. We use this hack so that we do not need
43// a new type name for each arity of type. (eg.,
44// BindState1, BindState2). This makes forward
45// declarations and friending much much easier.
ajwong@chromium.orge2cca632011-02-15 10:27:38 +090046//
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +090047// Types:
48// RunnableAdapter<> -- Wraps the various "function" pointer types into an
49// object that adheres to the Runnable interface.
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +090050// ForceVoidReturn<> -- Helper class for translating function signatures to
51// equivalent forms with a "void" return type.
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +090052// FunctorTraits<> -- Type traits used determine the correct RunType and
53// RunnableType for a Functor. This is where function
54// signature adapters are applied.
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +090055// MakeRunnable<> -- Takes a Functor and returns an object in the Runnable
56// type class that represents the underlying Functor.
57// There are |O(1)| MakeRunnable types.
58// InvokeHelper<> -- Take a Runnable + arguments and actully invokes it.
tzik07e99402015-02-06 04:11:26 +090059// Handle the differing syntaxes needed for WeakPtr<>
60// support, and for ignoring return values. This is separate
61// from Invoker to avoid creating multiple version of
62// Invoker<>.
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +090063// Invoker<> -- Unwraps the curried parameters and executes the Runnable.
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +090064// BindState<> -- Stores the curried parameters, and is the main entry point
65// into the Bind() system, doing most of the type resolution.
66// There are ARITY BindState types.
ajwong@chromium.orge0648232011-02-19 09:52:15 +090067
tzik8df08a52014-11-26 16:54:58 +090068// HasNonConstReferenceParam selects true_type when any of the parameters in
69// |Sig| is a non-const reference.
70// Implementation note: This non-specialized case handles zero-arity case only.
71// Non-zero-arity cases should be handled by the specialization below.
72template <typename Sig>
73struct HasNonConstReferenceParam : false_type {};
74
75// Implementation note: Select true_type if the first parameter is a non-const
76// reference. Otherwise, skip the first parameter and check rest of parameters
77// recursively.
78template <typename R, typename T, typename... Args>
79struct HasNonConstReferenceParam<R(T, Args...)>
80 : SelectType<is_non_const_reference<T>::value,
81 true_type,
82 HasNonConstReferenceParam<R(Args...)>>::Type {};
83
84// HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw
85// pointer to a RefCounted type.
86// Implementation note: This non-specialized case handles zero-arity case only.
87// Non-zero-arity cases should be handled by the specialization below.
88template <typename... Args>
89struct HasRefCountedTypeAsRawPtr : false_type {};
90
91// Implementation note: Select true_type if the first parameter is a raw pointer
92// to a RefCounted type. Otherwise, skip the first parameter and check rest of
93// parameters recursively.
94template <typename T, typename... Args>
95struct HasRefCountedTypeAsRawPtr<T, Args...>
96 : SelectType<NeedsScopedRefptrButGetsRawPtr<T>::value,
97 true_type,
98 HasRefCountedTypeAsRawPtr<Args...>>::Type {};
99
100// BindsArrayToFirstArg selects true_type when |is_method| is true and the first
101// item of |Args| is an array type.
102// Implementation note: This non-specialized case handles !is_method case and
103// zero-arity case only. Other cases should be handled by the specialization
104// below.
105template <bool is_method, typename... Args>
106struct BindsArrayToFirstArg : false_type {};
107
108template <typename T, typename... Args>
109struct BindsArrayToFirstArg<true, T, Args...> : is_array<T> {};
110
111// HasRefCountedParamAsRawPtr is the same to HasRefCountedTypeAsRawPtr except
112// when |is_method| is true HasRefCountedParamAsRawPtr skips the first argument.
113// Implementation note: This non-specialized case handles !is_method case and
114// zero-arity case only. Other cases should be handled by the specialization
115// below.
116template <bool is_method, typename... Args>
117struct HasRefCountedParamAsRawPtr : HasRefCountedTypeAsRawPtr<Args...> {};
118
119template <typename T, typename... Args>
120struct HasRefCountedParamAsRawPtr<true, T, Args...>
121 : HasRefCountedTypeAsRawPtr<Args...> {};
122
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900123// RunnableAdapter<>
124//
125// The RunnableAdapter<> templates provide a uniform interface for invoking
126// a function pointer, method pointer, or const method pointer. The adapter
127// exposes a Run() method with an appropriate signature. Using this wrapper
128// allows for writing code that supports all three pointer types without
129// undue repetition. Without it, a lot of code would need to be repeated 3
130// times.
131//
132// For method pointers and const method pointers the first argument to Run()
133// is considered to be the received of the method. This is similar to STL's
134// mem_fun().
135//
136// This class also exposes a RunType typedef that is the function type of the
137// Run() function.
138//
139// If and only if the wrapper contains a method or const method pointer, an
140// IsMethod typedef is exposed. The existence of this typedef (NOT the value)
141// marks that the wrapper should be considered a method wrapper.
ajwong@chromium.orgc711b822011-05-17 07:35:14 +0900142
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900143template <typename Functor>
144class RunnableAdapter;
ajwong@chromium.orge0648232011-02-19 09:52:15 +0900145
tzik012481a2014-11-20 19:09:45 +0900146// Function.
147template <typename R, typename... Args>
148class RunnableAdapter<R(*)(Args...)> {
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900149 public:
tzik012481a2014-11-20 19:09:45 +0900150 typedef R (RunType)(Args...);
ajwong@chromium.orga7e74822011-03-24 11:02:17 +0900151
tzik012481a2014-11-20 19:09:45 +0900152 explicit RunnableAdapter(R(*function)(Args...))
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900153 : function_(function) {
154 }
ajwong@chromium.orgc711b822011-05-17 07:35:14 +0900155
tzik012481a2014-11-20 19:09:45 +0900156 R Run(typename CallbackParamTraits<Args>::ForwardType... args) {
157 return function_(CallbackForward(args)...);
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900158 }
159
160 private:
tzik012481a2014-11-20 19:09:45 +0900161 R (*function_)(Args...);
ajwong@chromium.orge0648232011-02-19 09:52:15 +0900162};
163
tzik012481a2014-11-20 19:09:45 +0900164// Method.
165template <typename R, typename T, typename... Args>
166class RunnableAdapter<R(T::*)(Args...)> {
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900167 public:
tzik012481a2014-11-20 19:09:45 +0900168 typedef R (RunType)(T*, Args...);
ajwong@chromium.orgcb175342011-02-27 10:25:59 +0900169 typedef true_type IsMethod;
ajwong@chromium.orga7e74822011-03-24 11:02:17 +0900170
tzik012481a2014-11-20 19:09:45 +0900171 explicit RunnableAdapter(R(T::*method)(Args...))
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900172 : method_(method) {
173 }
ajwong@chromium.orgc711b822011-05-17 07:35:14 +0900174
tzik012481a2014-11-20 19:09:45 +0900175 R Run(T* object, typename CallbackParamTraits<Args>::ForwardType... args) {
176 return (object->*method_)(CallbackForward(args)...);
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900177 }
ajwong@chromium.orga7e74822011-03-24 11:02:17 +0900178
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900179 private:
tzik012481a2014-11-20 19:09:45 +0900180 R (T::*method_)(Args...);
ajwong@chromium.orge0648232011-02-19 09:52:15 +0900181};
182
tzik012481a2014-11-20 19:09:45 +0900183// Const Method.
184template <typename R, typename T, typename... Args>
185class RunnableAdapter<R(T::*)(Args...) const> {
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900186 public:
tzik012481a2014-11-20 19:09:45 +0900187 typedef R (RunType)(const T*, Args...);
ajwong@chromium.orgcb175342011-02-27 10:25:59 +0900188 typedef true_type IsMethod;
ajwong@chromium.orga7e74822011-03-24 11:02:17 +0900189
tzik012481a2014-11-20 19:09:45 +0900190 explicit RunnableAdapter(R(T::*method)(Args...) const)
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900191 : method_(method) {
192 }
ajwong@chromium.orgc711b822011-05-17 07:35:14 +0900193
tzik012481a2014-11-20 19:09:45 +0900194 R Run(const T* object,
195 typename CallbackParamTraits<Args>::ForwardType... args) {
196 return (object->*method_)(CallbackForward(args)...);
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900197 }
ajwong@chromium.orga7e74822011-03-24 11:02:17 +0900198
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900199 private:
tzik012481a2014-11-20 19:09:45 +0900200 R (T::*method_)(Args...) const;
ajwong@chromium.orge0648232011-02-19 09:52:15 +0900201};
202
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900203
204// ForceVoidReturn<>
205//
206// Set of templates that support forcing the function return type to void.
207template <typename Sig>
208struct ForceVoidReturn;
209
tzik012481a2014-11-20 19:09:45 +0900210template <typename R, typename... Args>
211struct ForceVoidReturn<R(Args...)> {
212 typedef void(RunType)(Args...);
ajwong@chromium.org6f015bd2011-11-29 07:13:54 +0900213};
214
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900215
216// FunctorTraits<>
217//
218// See description at top of file.
219template <typename T>
220struct FunctorTraits {
221 typedef RunnableAdapter<T> RunnableType;
222 typedef typename RunnableType::RunType RunType;
223};
224
225template <typename T>
tzik07e99402015-02-06 04:11:26 +0900226struct FunctorTraits<IgnoreResultHelper<T>> {
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900227 typedef typename FunctorTraits<T>::RunnableType RunnableType;
228 typedef typename ForceVoidReturn<
229 typename RunnableType::RunType>::RunType RunType;
230};
231
232template <typename T>
tzik07e99402015-02-06 04:11:26 +0900233struct FunctorTraits<Callback<T>> {
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900234 typedef Callback<T> RunnableType;
235 typedef typename Callback<T>::RunType RunType;
236};
237
238
239// MakeRunnable<>
240//
241// Converts a passed in functor to a RunnableType using type inference.
242
243template <typename T>
244typename FunctorTraits<T>::RunnableType MakeRunnable(const T& t) {
245 return RunnableAdapter<T>(t);
246}
247
248template <typename T>
249typename FunctorTraits<T>::RunnableType
250MakeRunnable(const IgnoreResultHelper<T>& t) {
251 return MakeRunnable(t.functor_);
252}
253
254template <typename T>
tzik07e99402015-02-06 04:11:26 +0900255const typename FunctorTraits<Callback<T>>::RunnableType&
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900256MakeRunnable(const Callback<T>& t) {
hashimoto@chromium.orgbc14c572012-11-20 17:28:14 +0900257 DCHECK(!t.is_null());
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900258 return t;
259}
260
261
262// InvokeHelper<>
263//
264// There are 3 logical InvokeHelper<> specializations: normal, void-return,
265// WeakCalls.
266//
267// The normal type just calls the underlying runnable.
268//
269// We need a InvokeHelper to handle void return types in order to support
270// IgnoreResult(). Normally, if the Runnable's RunType had a void return,
271// the template system would just accept "return functor.Run()" ignoring
272// the fact that a void function is being used with return. This piece of
273// sugar breaks though when the Runnable's RunType is not void. Thus, we
274// need a partial specialization to change the syntax to drop the "return"
275// from the invocation call.
276//
277// WeakCalls similarly need special syntax that is applied to the first
278// argument to check if they should no-op themselves.
279template <bool IsWeakCall, typename ReturnType, typename Runnable,
280 typename ArgsType>
281struct InvokeHelper;
282
tzik012481a2014-11-20 19:09:45 +0900283template <typename ReturnType, typename Runnable, typename... Args>
tzik07e99402015-02-06 04:11:26 +0900284struct InvokeHelper<false, ReturnType, Runnable, TypeList<Args...>> {
tzik012481a2014-11-20 19:09:45 +0900285 static ReturnType MakeItSo(Runnable runnable, Args... args) {
286 return runnable.Run(CallbackForward(args)...);
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900287 }
288};
289
tzik012481a2014-11-20 19:09:45 +0900290template <typename Runnable, typename... Args>
tzik07e99402015-02-06 04:11:26 +0900291struct InvokeHelper<false, void, Runnable, TypeList<Args...>> {
tzik012481a2014-11-20 19:09:45 +0900292 static void MakeItSo(Runnable runnable, Args... args) {
293 runnable.Run(CallbackForward(args)...);
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900294 }
295};
296
tzik012481a2014-11-20 19:09:45 +0900297template <typename Runnable, typename BoundWeakPtr, typename... Args>
tzik07e99402015-02-06 04:11:26 +0900298struct InvokeHelper<true, void, Runnable, TypeList<BoundWeakPtr, Args...>> {
tzik012481a2014-11-20 19:09:45 +0900299 static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, Args... args) {
akalin@chromium.orgd276ffa2013-06-04 07:15:21 +0900300 if (!weak_ptr.get()) {
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900301 return;
302 }
tzik012481a2014-11-20 19:09:45 +0900303 runnable.Run(weak_ptr.get(), CallbackForward(args)...);
ajwong@chromium.org6f015bd2011-11-29 07:13:54 +0900304 }
305};
306
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900307#if !defined(_MSC_VER)
308
309template <typename ReturnType, typename Runnable, typename ArgsType>
310struct InvokeHelper<true, ReturnType, Runnable, ArgsType> {
311 // WeakCalls are only supported for functions with a void return type.
312 // Otherwise, the function result would be undefined if the the WeakPtr<>
313 // is invalidated.
314 COMPILE_ASSERT(is_void<ReturnType>::value,
ajwong@chromium.orgc711b822011-05-17 07:35:14 +0900315 weak_ptrs_can_only_bind_to_methods_without_return_values);
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900316};
ajwong@chromium.orga7e74822011-03-24 11:02:17 +0900317
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900318#endif
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.
tzik07e99402015-02-06 04:11:26 +0900323template <typename BoundIndices,
324 typename StorageType, typename Unwrappers,
325 typename InvokeHelperType, typename UnboundForwardRunType>
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900326struct Invoker;
327
tzik07e99402015-02-06 04:11:26 +0900328template <size_t... bound_indices,
329 typename StorageType,
330 typename... Unwrappers,
331 typename InvokeHelperType,
332 typename R,
333 typename... UnboundForwardArgs>
334struct Invoker<IndexSequence<bound_indices...>,
335 StorageType, TypeList<Unwrappers...>,
336 InvokeHelperType, R(UnboundForwardArgs...)> {
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900337 static R Run(BindStateBase* base,
tzik07e99402015-02-06 04:11:26 +0900338 UnboundForwardArgs... unbound_args) {
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900339 StorageType* storage = static_cast<StorageType*>(base);
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900340 // Local references to make debugger stepping easier. If in a debugger,
341 // you really want to warp ahead and step through the
342 // InvokeHelper<>::MakeItSo() call below.
tzik07e99402015-02-06 04:11:26 +0900343 return InvokeHelperType::MakeItSo(
344 storage->runnable_,
345 Unwrappers::Unwrap(get<bound_indices>(storage->bound_args_))...,
346 CallbackForward(unbound_args)...);
ajwong@chromium.org6f015bd2011-11-29 07:13:54 +0900347 }
348};
349
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900350
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900351// BindState<>
352//
353// This stores all the state passed into Bind() and is also where most
354// of the template resolution magic occurs.
355//
356// Runnable is the functor we are binding arguments to.
357// RunType is type of the Run() function that the Invoker<> should use.
358// Normally, this is the same as the RunType of the Runnable, but it can
359// be different if an adapter like IgnoreResult() has been used.
360//
361// BoundArgsType contains the storage type for all the bound arguments by
362// (ab)using a function type.
tzik07e99402015-02-06 04:11:26 +0900363template <typename Runnable, typename RunType, typename BoundArgList>
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900364struct BindState;
365
tzik07e99402015-02-06 04:11:26 +0900366template <typename Runnable,
tapted9cef4212015-05-14 17:03:32 +0900367 typename R,
368 typename... Args,
tzik07e99402015-02-06 04:11:26 +0900369 typename... BoundArgs>
tapted9cef4212015-05-14 17:03:32 +0900370struct BindState<Runnable, R(Args...), TypeList<BoundArgs...>> final
tzik07e99402015-02-06 04:11:26 +0900371 : public BindStateBase {
372 private:
373 using StorageType = BindState<Runnable, R(Args...), TypeList<BoundArgs...>>;
374 using RunnableType = Runnable;
375
376 // true_type if Runnable is a method invocation and the first bound argument
377 // is a WeakPtr.
378 using IsWeakCall =
379 IsWeakMethod<HasIsMethodTag<Runnable>::value, BoundArgs...>;
380
381 using BoundIndices = MakeIndexSequence<sizeof...(BoundArgs)>;
382 using Unwrappers = TypeList<UnwrapTraits<BoundArgs>...>;
383 using UnboundForwardArgs = DropTypeListItem<
384 sizeof...(BoundArgs),
385 TypeList<typename CallbackParamTraits<Args>::ForwardType...>>;
386 using UnboundForwardRunType = MakeFunctionType<R, UnboundForwardArgs>;
387
388 using InvokeHelperArgs = ConcatTypeLists<
389 TypeList<typename UnwrapTraits<BoundArgs>::ForwardType...>,
390 UnboundForwardArgs>;
391 using InvokeHelperType =
392 InvokeHelper<IsWeakCall::value, R, Runnable, InvokeHelperArgs>;
393
394 using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), TypeList<Args...>>;
395
396 public:
397 using InvokerType = Invoker<BoundIndices, StorageType, Unwrappers,
398 InvokeHelperType, UnboundForwardRunType>;
399 using UnboundRunType = MakeFunctionType<R, UnboundArgs>;
400
401 BindState(const Runnable& runnable, const BoundArgs&... bound_args)
tapted9cef4212015-05-14 17:03:32 +0900402 : BindStateBase(&Destroy),
403 runnable_(runnable),
404 ref_(bound_args...),
405 bound_args_(bound_args...) {}
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900406
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900407 RunnableType runnable_;
tzik07e99402015-02-06 04:11:26 +0900408 MaybeScopedRefPtr<HasIsMethodTag<Runnable>::value, BoundArgs...> ref_;
409 Tuple<BoundArgs...> bound_args_;
dmichael2f7bc202014-12-19 07:30:11 +0900410
411 private:
tapted9cef4212015-05-14 17:03:32 +0900412 ~BindState() {}
413
414 static void Destroy(BindStateBase* self) {
415 delete static_cast<BindState*>(self);
416 }
ajwong@chromium.org6f015bd2011-11-29 07:13:54 +0900417};
418
ajwong@chromium.orge2cca632011-02-15 10:27:38 +0900419} // namespace internal
420} // namespace base
421
422#endif // BASE_BIND_INTERNAL_H_