blob: 6d500a5568263b3b8d5cb77dd2d62ce6e0a55837 [file] [log] [blame]
Vitaly Bukacbed2062015-08-17 12:54:05 -07001// 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_
7
8#include "base/bind_helpers.h"
Vitaly Buka8750b272015-08-18 18:39:08 -07009#include "base/build/build_config.h"
Vitaly Bukacbed2062015-08-17 12:54:05 -070010#include "base/callback_internal.h"
Vitaly Bukacbed2062015-08-17 12:54:05 -070011#include "base/memory/weak_ptr.h"
12#include "base/template_util.h"
13#include "base/tuple.h"
Vitaly Bukacbed2062015-08-17 12:54:05 -070014
15#if defined(OS_WIN)
16#include "base/bind_internal_win.h"
17#endif
18
19namespace base {
20namespace internal {
21
22// See base/callback.h for user documentation.
23//
24//
25// CONCEPTS:
26// Runnable -- A type (really a type class) that has a single Run() method
27// and a RunType typedef that corresponds to the type of Run().
28// A Runnable can declare that it should treated like a method
29// call by including a typedef named IsMethod. The value of
30// this typedef is NOT inspected, only the existence. When a
31// Runnable declares itself a method, Bind() will enforce special
32// refcounting + WeakPtr handling semantics for the first
33// parameter which is expected to be an object.
34// Functor -- A copyable type representing something that should be called.
35// All function pointers, Callback<>, and Runnables are functors
36// even if the invocation syntax differs.
37// RunType -- A function type (as opposed to function _pointer_ type) for
38// a Run() function. Usually just a convenience typedef.
39// (Bound)ArgsType -- A function type that is being (ab)used to store the
40// types of set of arguments. The "return" type is always
41// void here. We use this hack so that we do not need
42// a new type name for each arity of type. (eg.,
43// BindState1, BindState2). This makes forward
44// declarations and friending much much easier.
45//
46// Types:
47// RunnableAdapter<> -- Wraps the various "function" pointer types into an
48// object that adheres to the Runnable interface.
49// ForceVoidReturn<> -- Helper class for translating function signatures to
50// equivalent forms with a "void" return type.
51// FunctorTraits<> -- Type traits used determine the correct RunType and
52// RunnableType for a Functor. This is where function
53// signature adapters are applied.
54// MakeRunnable<> -- Takes a Functor and returns an object in the Runnable
55// type class that represents the underlying Functor.
56// There are |O(1)| MakeRunnable types.
57// InvokeHelper<> -- Take a Runnable + arguments and actully invokes it.
58// Handle the differing syntaxes needed for WeakPtr<>
59// support, and for ignoring return values. This is separate
60// from Invoker to avoid creating multiple version of
61// Invoker<>.
62// Invoker<> -- Unwraps the curried parameters and executes the Runnable.
63// BindState<> -- Stores the curried parameters, and is the main entry point
64// into the Bind() system, doing most of the type resolution.
65// There are ARITY BindState types.
66
67// HasNonConstReferenceParam selects true_type when any of the parameters in
68// |Sig| is a non-const reference.
69// Implementation note: This non-specialized case handles zero-arity case only.
70// Non-zero-arity cases should be handled by the specialization below.
71template <typename Sig>
Vitaly Buka8750b272015-08-18 18:39:08 -070072struct HasNonConstReferenceParam : std::false_type {};
Vitaly Bukacbed2062015-08-17 12:54:05 -070073
74// Implementation note: Select true_type if the first parameter is a non-const
75// reference. Otherwise, skip the first parameter and check rest of parameters
76// recursively.
77template <typename R, typename T, typename... Args>
78struct HasNonConstReferenceParam<R(T, Args...)>
79 : SelectType<is_non_const_reference<T>::value,
Vitaly Buka8750b272015-08-18 18:39:08 -070080 std::true_type,
Vitaly Bukacbed2062015-08-17 12:54:05 -070081 HasNonConstReferenceParam<R(Args...)>>::Type {};
82
83// HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw
84// pointer to a RefCounted type.
85// Implementation note: This non-specialized case handles zero-arity case only.
86// Non-zero-arity cases should be handled by the specialization below.
87template <typename... Args>
Vitaly Buka8750b272015-08-18 18:39:08 -070088struct HasRefCountedTypeAsRawPtr : std::false_type {};
Vitaly Bukacbed2062015-08-17 12:54:05 -070089
90// BindsArrayToFirstArg selects true_type when |is_method| is true and the first
91// item of |Args| is an array type.
92// Implementation note: This non-specialized case handles !is_method case and
93// zero-arity case only. Other cases should be handled by the specialization
94// below.
95template <bool is_method, typename... Args>
Vitaly Buka8750b272015-08-18 18:39:08 -070096struct BindsArrayToFirstArg : std::false_type {};
Vitaly Bukacbed2062015-08-17 12:54:05 -070097
98template <typename T, typename... Args>
Vitaly Buka8750b272015-08-18 18:39:08 -070099struct BindsArrayToFirstArg<true, T, Args...> : std::is_array<T> {};
Vitaly Bukacbed2062015-08-17 12:54:05 -0700100
101// HasRefCountedParamAsRawPtr is the same to HasRefCountedTypeAsRawPtr except
102// when |is_method| is true HasRefCountedParamAsRawPtr skips the first argument.
103// Implementation note: This non-specialized case handles !is_method case and
104// zero-arity case only. Other cases should be handled by the specialization
105// below.
106template <bool is_method, typename... Args>
107struct HasRefCountedParamAsRawPtr : HasRefCountedTypeAsRawPtr<Args...> {};
108
109template <typename T, typename... Args>
110struct HasRefCountedParamAsRawPtr<true, T, Args...>
111 : HasRefCountedTypeAsRawPtr<Args...> {};
112
113// RunnableAdapter<>
114//
115// The RunnableAdapter<> templates provide a uniform interface for invoking
116// a function pointer, method pointer, or const method pointer. The adapter
117// exposes a Run() method with an appropriate signature. Using this wrapper
118// allows for writing code that supports all three pointer types without
119// undue repetition. Without it, a lot of code would need to be repeated 3
120// times.
121//
122// For method pointers and const method pointers the first argument to Run()
123// is considered to be the received of the method. This is similar to STL's
124// mem_fun().
125//
126// This class also exposes a RunType typedef that is the function type of the
127// Run() function.
128//
129// If and only if the wrapper contains a method or const method pointer, an
130// IsMethod typedef is exposed. The existence of this typedef (NOT the value)
131// marks that the wrapper should be considered a method wrapper.
132
133template <typename Functor>
134class RunnableAdapter;
135
136// Function.
137template <typename R, typename... Args>
138class RunnableAdapter<R(*)(Args...)> {
139 public:
140 typedef R (RunType)(Args...);
141
142 explicit RunnableAdapter(R(*function)(Args...))
143 : function_(function) {
144 }
145
146 R Run(typename CallbackParamTraits<Args>::ForwardType... args) {
147 return function_(CallbackForward(args)...);
148 }
149
150 private:
151 R (*function_)(Args...);
152};
153
154// Method.
155template <typename R, typename T, typename... Args>
156class RunnableAdapter<R(T::*)(Args...)> {
157 public:
158 typedef R (RunType)(T*, Args...);
Vitaly Buka8750b272015-08-18 18:39:08 -0700159 typedef std::true_type IsMethod;
Vitaly Bukacbed2062015-08-17 12:54:05 -0700160
161 explicit RunnableAdapter(R(T::*method)(Args...))
162 : method_(method) {
163 }
164
165 R Run(T* object, typename CallbackParamTraits<Args>::ForwardType... args) {
166 return (object->*method_)(CallbackForward(args)...);
167 }
168
169 private:
170 R (T::*method_)(Args...);
171};
172
173// Const Method.
174template <typename R, typename T, typename... Args>
175class RunnableAdapter<R(T::*)(Args...) const> {
176 public:
177 typedef R (RunType)(const T*, Args...);
Vitaly Buka8750b272015-08-18 18:39:08 -0700178 typedef std::true_type IsMethod;
Vitaly Bukacbed2062015-08-17 12:54:05 -0700179
180 explicit RunnableAdapter(R(T::*method)(Args...) const)
181 : method_(method) {
182 }
183
184 R Run(const T* object,
185 typename CallbackParamTraits<Args>::ForwardType... args) {
186 return (object->*method_)(CallbackForward(args)...);
187 }
188
189 private:
190 R (T::*method_)(Args...) const;
191};
192
193
194// ForceVoidReturn<>
195//
196// Set of templates that support forcing the function return type to void.
197template <typename Sig>
198struct ForceVoidReturn;
199
200template <typename R, typename... Args>
201struct ForceVoidReturn<R(Args...)> {
202 typedef void(RunType)(Args...);
203};
204
205
206// FunctorTraits<>
207//
208// See description at top of file.
209template <typename T>
210struct FunctorTraits {
211 typedef RunnableAdapter<T> RunnableType;
212 typedef typename RunnableType::RunType RunType;
213};
214
215template <typename T>
216struct FunctorTraits<IgnoreResultHelper<T>> {
217 typedef typename FunctorTraits<T>::RunnableType RunnableType;
218 typedef typename ForceVoidReturn<
219 typename RunnableType::RunType>::RunType RunType;
220};
221
222template <typename T>
223struct FunctorTraits<Callback<T>> {
224 typedef Callback<T> RunnableType;
225 typedef typename Callback<T>::RunType RunType;
226};
227
228
229// MakeRunnable<>
230//
231// Converts a passed in functor to a RunnableType using type inference.
232
233template <typename T>
234typename FunctorTraits<T>::RunnableType MakeRunnable(const T& t) {
235 return RunnableAdapter<T>(t);
236}
237
238template <typename T>
239typename FunctorTraits<T>::RunnableType
240MakeRunnable(const IgnoreResultHelper<T>& t) {
241 return MakeRunnable(t.functor_);
242}
243
244template <typename T>
245const typename FunctorTraits<Callback<T>>::RunnableType&
246MakeRunnable(const Callback<T>& t) {
247 DCHECK(!t.is_null());
248 return t;
249}
250
251
252// InvokeHelper<>
253//
254// There are 3 logical InvokeHelper<> specializations: normal, void-return,
255// WeakCalls.
256//
257// The normal type just calls the underlying runnable.
258//
259// We need a InvokeHelper to handle void return types in order to support
260// IgnoreResult(). Normally, if the Runnable's RunType had a void return,
261// the template system would just accept "return functor.Run()" ignoring
262// the fact that a void function is being used with return. This piece of
263// sugar breaks though when the Runnable's RunType is not void. Thus, we
264// need a partial specialization to change the syntax to drop the "return"
265// from the invocation call.
266//
267// WeakCalls similarly need special syntax that is applied to the first
268// argument to check if they should no-op themselves.
269template <bool IsWeakCall, typename ReturnType, typename Runnable,
270 typename ArgsType>
271struct InvokeHelper;
272
273template <typename ReturnType, typename Runnable, typename... Args>
274struct InvokeHelper<false, ReturnType, Runnable, TypeList<Args...>> {
275 static ReturnType MakeItSo(Runnable runnable, Args... args) {
276 return runnable.Run(CallbackForward(args)...);
277 }
278};
279
280template <typename Runnable, typename... Args>
281struct InvokeHelper<false, void, Runnable, TypeList<Args...>> {
282 static void MakeItSo(Runnable runnable, Args... args) {
283 runnable.Run(CallbackForward(args)...);
284 }
285};
286
287template <typename Runnable, typename BoundWeakPtr, typename... Args>
288struct InvokeHelper<true, void, Runnable, TypeList<BoundWeakPtr, Args...>> {
289 static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, Args... args) {
290 if (!weak_ptr.get()) {
291 return;
292 }
293 runnable.Run(weak_ptr.get(), CallbackForward(args)...);
294 }
295};
296
297#if !defined(_MSC_VER)
298
299template <typename ReturnType, typename Runnable, typename ArgsType>
300struct InvokeHelper<true, ReturnType, Runnable, ArgsType> {
301 // 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.
Vitaly Buka8750b272015-08-18 18:39:08 -0700304 COMPILE_ASSERT(std::is_void<ReturnType>::value,
Vitaly Bukacbed2062015-08-17 12:54:05 -0700305 weak_ptrs_can_only_bind_to_methods_without_return_values);
306};
307
308#endif
309
310// Invoker<>
311//
312// See description at the top of the file.
313template <typename BoundIndices,
314 typename StorageType, typename Unwrappers,
315 typename InvokeHelperType, typename UnboundForwardRunType>
316struct Invoker;
317
318template <size_t... bound_indices,
319 typename StorageType,
320 typename... Unwrappers,
321 typename InvokeHelperType,
322 typename R,
323 typename... UnboundForwardArgs>
324struct Invoker<IndexSequence<bound_indices...>,
325 StorageType, TypeList<Unwrappers...>,
326 InvokeHelperType, R(UnboundForwardArgs...)> {
327 static R Run(BindStateBase* base,
328 UnboundForwardArgs... unbound_args) {
329 StorageType* storage = static_cast<StorageType*>(base);
330 // 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 return InvokeHelperType::MakeItSo(
334 storage->runnable_,
335 Unwrappers::Unwrap(get<bound_indices>(storage->bound_args_))...,
336 CallbackForward(unbound_args)...);
337 }
338};
339
340
341// BindState<>
342//
343// This stores all the state passed into Bind() and is also where most
344// of the template resolution magic occurs.
345//
346// Runnable is the functor we are binding arguments to.
347// RunType is type of the Run() function that the Invoker<> should use.
348// Normally, this is the same as the RunType of the Runnable, but it can
349// be different if an adapter like IgnoreResult() has been used.
350//
351// BoundArgsType contains the storage type for all the bound arguments by
352// (ab)using a function type.
353template <typename Runnable, typename RunType, typename BoundArgList>
354struct BindState;
355
356template <typename Runnable,
357 typename R,
358 typename... Args,
359 typename... BoundArgs>
360struct BindState<Runnable, R(Args...), TypeList<BoundArgs...>> final
361 : public BindStateBase {
362 private:
363 using StorageType = BindState<Runnable, R(Args...), TypeList<BoundArgs...>>;
364 using RunnableType = Runnable;
365
366 // true_type if Runnable is a method invocation and the first bound argument
367 // is a WeakPtr.
368 using IsWeakCall =
369 IsWeakMethod<HasIsMethodTag<Runnable>::value, BoundArgs...>;
370
371 using BoundIndices = MakeIndexSequence<sizeof...(BoundArgs)>;
372 using Unwrappers = TypeList<UnwrapTraits<BoundArgs>...>;
373 using UnboundForwardArgs = DropTypeListItem<
374 sizeof...(BoundArgs),
375 TypeList<typename CallbackParamTraits<Args>::ForwardType...>>;
376 using UnboundForwardRunType = MakeFunctionType<R, UnboundForwardArgs>;
377
378 using InvokeHelperArgs = ConcatTypeLists<
379 TypeList<typename UnwrapTraits<BoundArgs>::ForwardType...>,
380 UnboundForwardArgs>;
381 using InvokeHelperType =
382 InvokeHelper<IsWeakCall::value, R, Runnable, InvokeHelperArgs>;
383
384 using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), TypeList<Args...>>;
385
386 public:
387 using InvokerType = Invoker<BoundIndices, StorageType, Unwrappers,
388 InvokeHelperType, UnboundForwardRunType>;
389 using UnboundRunType = MakeFunctionType<R, UnboundArgs>;
390
391 BindState(const Runnable& runnable, const BoundArgs&... bound_args)
392 : BindStateBase(&Destroy),
393 runnable_(runnable),
394 ref_(bound_args...),
395 bound_args_(bound_args...) {}
396
397 RunnableType runnable_;
398 MaybeScopedRefPtr<HasIsMethodTag<Runnable>::value, BoundArgs...> ref_;
399 Tuple<BoundArgs...> bound_args_;
400
401 private:
402 ~BindState() {}
403
404 static void Destroy(BindStateBase* self) {
405 delete static_cast<BindState*>(self);
406 }
407};
408
409} // namespace internal
410} // namespace base
411
412#endif // BASE_BIND_INTERNAL_H_