Add ICU message format support
[chromium-blink-merge.git] / base / bind_internal.h
blobe05321886223f8863693aba9e910408dc463696e
1 // 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.
5 #ifndef BASE_BIND_INTERNAL_H_
6 #define BASE_BIND_INTERNAL_H_
8 #include "base/bind_helpers.h"
9 #include "base/callback_internal.h"
10 #include "base/memory/raw_scoped_refptr_mismatch_checker.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/template_util.h"
13 #include "base/tuple.h"
14 #include "build/build_config.h"
16 #if defined(OS_WIN)
17 #include "base/bind_internal_win.h"
18 #endif
20 namespace base {
21 namespace internal {
23 // See base/callback.h for user documentation.
26 // 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.
47 // Types:
48 // RunnableAdapter<> -- Wraps the various "function" pointer types into an
49 // object that adheres to the Runnable interface.
50 // ForceVoidReturn<> -- Helper class for translating function signatures to
51 // equivalent forms with a "void" return type.
52 // FunctorTraits<> -- Type traits used determine the correct RunType and
53 // RunnableType for a Functor. This is where function
54 // signature adapters are applied.
55 // 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.
59 // 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<>.
63 // Invoker<> -- Unwraps the curried parameters and executes the Runnable.
64 // 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.
68 // 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.
72 template <typename Sig>
73 struct HasNonConstReferenceParam : false_type {};
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.
78 template <typename R, typename T, typename... Args>
79 struct HasNonConstReferenceParam<R(T, Args...)>
80 : SelectType<is_non_const_reference<T>::value,
81 true_type,
82 HasNonConstReferenceParam<R(Args...)>>::Type {};
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.
88 template <typename... Args>
89 struct HasRefCountedTypeAsRawPtr : false_type {};
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.
94 template <typename T, typename... Args>
95 struct HasRefCountedTypeAsRawPtr<T, Args...>
96 : SelectType<NeedsScopedRefptrButGetsRawPtr<T>::value,
97 true_type,
98 HasRefCountedTypeAsRawPtr<Args...>>::Type {};
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.
105 template <bool is_method, typename... Args>
106 struct BindsArrayToFirstArg : false_type {};
108 template <typename T, typename... Args>
109 struct BindsArrayToFirstArg<true, T, Args...> : is_array<T> {};
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.
116 template <bool is_method, typename... Args>
117 struct HasRefCountedParamAsRawPtr : HasRefCountedTypeAsRawPtr<Args...> {};
119 template <typename T, typename... Args>
120 struct HasRefCountedParamAsRawPtr<true, T, Args...>
121 : HasRefCountedTypeAsRawPtr<Args...> {};
123 // RunnableAdapter<>
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.
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().
136 // This class also exposes a RunType typedef that is the function type of the
137 // Run() function.
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.
143 template <typename Functor>
144 class RunnableAdapter;
146 // Function.
147 template <typename R, typename... Args>
148 class RunnableAdapter<R(*)(Args...)> {
149 public:
150 typedef R (RunType)(Args...);
152 explicit RunnableAdapter(R(*function)(Args...))
153 : function_(function) {
156 R Run(typename CallbackParamTraits<Args>::ForwardType... args) {
157 return function_(CallbackForward(args)...);
160 private:
161 R (*function_)(Args...);
164 // Method.
165 template <typename R, typename T, typename... Args>
166 class RunnableAdapter<R(T::*)(Args...)> {
167 public:
168 typedef R (RunType)(T*, Args...);
169 typedef true_type IsMethod;
171 explicit RunnableAdapter(R(T::*method)(Args...))
172 : method_(method) {
175 R Run(T* object, typename CallbackParamTraits<Args>::ForwardType... args) {
176 return (object->*method_)(CallbackForward(args)...);
179 private:
180 R (T::*method_)(Args...);
183 // Const Method.
184 template <typename R, typename T, typename... Args>
185 class RunnableAdapter<R(T::*)(Args...) const> {
186 public:
187 typedef R (RunType)(const T*, Args...);
188 typedef true_type IsMethod;
190 explicit RunnableAdapter(R(T::*method)(Args...) const)
191 : method_(method) {
194 R Run(const T* object,
195 typename CallbackParamTraits<Args>::ForwardType... args) {
196 return (object->*method_)(CallbackForward(args)...);
199 private:
200 R (T::*method_)(Args...) const;
204 // ForceVoidReturn<>
206 // Set of templates that support forcing the function return type to void.
207 template <typename Sig>
208 struct ForceVoidReturn;
210 template <typename R, typename... Args>
211 struct ForceVoidReturn<R(Args...)> {
212 typedef void(RunType)(Args...);
216 // FunctorTraits<>
218 // See description at top of file.
219 template <typename T>
220 struct FunctorTraits {
221 typedef RunnableAdapter<T> RunnableType;
222 typedef typename RunnableType::RunType RunType;
225 template <typename T>
226 struct FunctorTraits<IgnoreResultHelper<T>> {
227 typedef typename FunctorTraits<T>::RunnableType RunnableType;
228 typedef typename ForceVoidReturn<
229 typename RunnableType::RunType>::RunType RunType;
232 template <typename T>
233 struct FunctorTraits<Callback<T>> {
234 typedef Callback<T> RunnableType;
235 typedef typename Callback<T>::RunType RunType;
239 // MakeRunnable<>
241 // Converts a passed in functor to a RunnableType using type inference.
243 template <typename T>
244 typename FunctorTraits<T>::RunnableType MakeRunnable(const T& t) {
245 return RunnableAdapter<T>(t);
248 template <typename T>
249 typename FunctorTraits<T>::RunnableType
250 MakeRunnable(const IgnoreResultHelper<T>& t) {
251 return MakeRunnable(t.functor_);
254 template <typename T>
255 const typename FunctorTraits<Callback<T>>::RunnableType&
256 MakeRunnable(const Callback<T>& t) {
257 DCHECK(!t.is_null());
258 return t;
262 // InvokeHelper<>
264 // There are 3 logical InvokeHelper<> specializations: normal, void-return,
265 // WeakCalls.
267 // The normal type just calls the underlying runnable.
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.
277 // WeakCalls similarly need special syntax that is applied to the first
278 // argument to check if they should no-op themselves.
279 template <bool IsWeakCall, typename ReturnType, typename Runnable,
280 typename ArgsType>
281 struct InvokeHelper;
283 template <typename ReturnType, typename Runnable, typename... Args>
284 struct InvokeHelper<false, ReturnType, Runnable, TypeList<Args...>> {
285 static ReturnType MakeItSo(Runnable runnable, Args... args) {
286 return runnable.Run(CallbackForward(args)...);
290 template <typename Runnable, typename... Args>
291 struct InvokeHelper<false, void, Runnable, TypeList<Args...>> {
292 static void MakeItSo(Runnable runnable, Args... args) {
293 runnable.Run(CallbackForward(args)...);
297 template <typename Runnable, typename BoundWeakPtr, typename... Args>
298 struct InvokeHelper<true, void, Runnable, TypeList<BoundWeakPtr, Args...>> {
299 static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, Args... args) {
300 if (!weak_ptr.get()) {
301 return;
303 runnable.Run(weak_ptr.get(), CallbackForward(args)...);
307 #if !defined(_MSC_VER)
309 template <typename ReturnType, typename Runnable, typename ArgsType>
310 struct 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,
315 weak_ptrs_can_only_bind_to_methods_without_return_values);
318 #endif
320 // Invoker<>
322 // See description at the top of the file.
323 template <typename BoundIndices,
324 typename StorageType, typename Unwrappers,
325 typename InvokeHelperType, typename UnboundForwardRunType>
326 struct Invoker;
328 template <size_t... bound_indices,
329 typename StorageType,
330 typename... Unwrappers,
331 typename InvokeHelperType,
332 typename R,
333 typename... UnboundForwardArgs>
334 struct Invoker<IndexSequence<bound_indices...>,
335 StorageType, TypeList<Unwrappers...>,
336 InvokeHelperType, R(UnboundForwardArgs...)> {
337 static R Run(BindStateBase* base,
338 UnboundForwardArgs... unbound_args) {
339 StorageType* storage = static_cast<StorageType*>(base);
340 // 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.
343 return InvokeHelperType::MakeItSo(
344 storage->runnable_,
345 Unwrappers::Unwrap(get<bound_indices>(storage->bound_args_))...,
346 CallbackForward(unbound_args)...);
351 // BindState<>
353 // This stores all the state passed into Bind() and is also where most
354 // of the template resolution magic occurs.
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.
361 // BoundArgsType contains the storage type for all the bound arguments by
362 // (ab)using a function type.
363 template <typename Runnable, typename RunType, typename BoundArgList>
364 struct BindState;
366 template <typename Runnable,
367 typename R,
368 typename... Args,
369 typename... BoundArgs>
370 struct BindState<Runnable, R(Args...), TypeList<BoundArgs...>> final
371 : public BindStateBase {
372 private:
373 using StorageType = BindState<Runnable, R(Args...), TypeList<BoundArgs...>>;
374 using RunnableType = Runnable;
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...>;
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>;
388 using InvokeHelperArgs = ConcatTypeLists<
389 TypeList<typename UnwrapTraits<BoundArgs>::ForwardType...>,
390 UnboundForwardArgs>;
391 using InvokeHelperType =
392 InvokeHelper<IsWeakCall::value, R, Runnable, InvokeHelperArgs>;
394 using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), TypeList<Args...>>;
396 public:
397 using InvokerType = Invoker<BoundIndices, StorageType, Unwrappers,
398 InvokeHelperType, UnboundForwardRunType>;
399 using UnboundRunType = MakeFunctionType<R, UnboundArgs>;
401 BindState(const Runnable& runnable, const BoundArgs&... bound_args)
402 : BindStateBase(&Destroy),
403 runnable_(runnable),
404 ref_(bound_args...),
405 bound_args_(bound_args...) {}
407 RunnableType runnable_;
408 MaybeScopedRefPtr<HasIsMethodTag<Runnable>::value, BoundArgs...> ref_;
409 Tuple<BoundArgs...> bound_args_;
411 private:
412 ~BindState() {}
414 static void Destroy(BindStateBase* self) {
415 delete static_cast<BindState*>(self);
419 } // namespace internal
420 } // namespace base
422 #endif // BASE_BIND_INTERNAL_H_