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