• 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 <tuple>
11 #include <type_traits>
12 
13 #include "base/bind_helpers.h"
14 #include "base/callback_internal.h"
15 #include "base/memory/raw_scoped_refptr_mismatch_checker.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/template_util.h"
18 #include "base/tuple.h"
19 #include "build/build_config.h"
20 
21 namespace base {
22 namespace internal {
23 
24 // See base/callback.h for user documentation.
25 //
26 //
27 // CONCEPTS:
28 //  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.
31 //  RunType -- A function type (as opposed to function _pointer_ type) for
32 //             a Callback<>::Run().  Usually just a convenience typedef.
33 //  (Bound)Args -- A set of types that stores the arguments.
34 //
35 // Types:
36 //  ForceVoidReturn<> -- Helper class for translating function signatures to
37 //                       equivalent forms with a "void" return type.
38 //  FunctorTraits<> -- Type traits used to determine the correct RunType and
39 //                     invocation manner for a Functor.  This is where function
40 //                     signature adapters are applied.
41 //  InvokeHelper<> -- Take a Functor + arguments and actully invokes it.
42 //                    Handle the differing syntaxes needed for WeakPtr<>
43 //                    support.  This is separate from Invoker to avoid creating
44 //                    multiple version of Invoker<>.
45 //  Invoker<> -- Unwraps the curried parameters and executes the Functor.
46 //  BindState<> -- Stores the curried parameters, and is the main entry point
47 //                 into the Bind() system.
48 
49 template <typename...>
50 struct 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
59 template <typename... Ts>
60 using void_t = typename make_void<Ts...>::type;
61 
62 template <typename Callable,
63           typename Signature = decltype(&Callable::operator())>
64 struct ExtractCallableRunTypeImpl;
65 
66 template <typename Callable, typename R, typename... Args>
67 struct 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*);
77 template <typename Callable>
78 using 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.
96 template <typename Functor, typename SFINAE = void>
97 struct IsConvertibleToRunType : std::false_type {};
98 
99 template <typename Callable>
100 struct IsConvertibleToRunType<Callable, void_t<decltype(&Callable::operator())>>
101     : std::is_convertible<Callable, ExtractCallableRunType<Callable>*> {};
102 
103 // 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.
107 template <typename... Args>
108 struct HasRefCountedTypeAsRawPtr : std::false_type {};
109 
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.
113 template <typename T, typename... Args>
114 struct HasRefCountedTypeAsRawPtr<T, Args...>
115     : std::conditional<NeedsScopedRefptrButGetsRawPtr<T>::value,
116                        std::true_type,
117                        HasRefCountedTypeAsRawPtr<Args...>>::type {};
118 
119 // ForceVoidReturn<>
120 //
121 // Set of templates that support forcing the function return type to void.
122 template <typename Sig>
123 struct ForceVoidReturn;
124 
125 template <typename R, typename... Args>
126 struct ForceVoidReturn<R(Args...)> {
127   using RunType = void(Args...);
128 };
129 
130 // FunctorTraits<>
131 //
132 // See description at top of file.
133 template <typename Functor, typename SFINAE = void>
134 struct FunctorTraits;
135 
136 // 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.
140 template <typename Functor>
141 struct 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 
155 // For functions.
156 template <typename R, typename... Args>
157 struct FunctorTraits<R (*)(Args...)> {
158   using RunType = R(Args...);
159   static constexpr bool is_method = false;
160   static constexpr bool is_nullable = true;
161 
162   template <typename... RunArgs>
163   static R Invoke(R (*function)(Args...), RunArgs&&... args) {
164     return function(std::forward<RunArgs>(args)...);
165   }
166 };
167 
168 #if defined(OS_WIN) && !defined(ARCH_CPU_X86_64)
169 
170 // For functions.
171 template <typename R, typename... Args>
172 struct FunctorTraits<R(__stdcall*)(Args...)> {
173   using RunType = R(Args...);
174   static constexpr bool is_method = false;
175   static constexpr bool is_nullable = true;
176 
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.
184 template <typename R, typename... Args>
185 struct FunctorTraits<R(__fastcall*)(Args...)> {
186   using RunType = R(Args...);
187   static constexpr bool is_method = false;
188   static constexpr bool is_nullable = true;
189 
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.
199 template <typename R, typename Receiver, typename... Args>
200 struct FunctorTraits<R (Receiver::*)(Args...)> {
201   using RunType = R(Receiver*, Args...);
202   static constexpr bool is_method = true;
203   static constexpr bool is_nullable = true;
204 
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.
219 template <typename R, typename Receiver, typename... Args>
220 struct FunctorTraits<R (Receiver::*)(Args...) const> {
221   using RunType = R(const Receiver*, Args...);
222   static constexpr bool is_method = true;
223   static constexpr bool is_nullable = true;
224 
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.
239 template <typename T>
240 struct FunctorTraits<IgnoreResultHelper<T>> : FunctorTraits<T> {
241   using RunType =
242       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) {
247     FunctorTraits<T>::Invoke(ignore_result_helper.functor_,
248                              std::forward<RunArgs>(args)...);
249   }
250 };
251 
252 // For Callbacks.
253 template <typename R, typename... Args, CopyMode copy_mode>
254 struct FunctorTraits<Callback<R(Args...), copy_mode>> {
255   using RunType = R(Args...);
256   static constexpr bool is_method = false;
257   static constexpr bool is_nullable = true;
258 
259   template <typename CallbackType, typename... RunArgs>
260   static R Invoke(CallbackType&& callback, RunArgs&&... args) {
261     DCHECK(!callback.is_null());
262     return std::forward<CallbackType>(callback).Run(
263         std::forward<RunArgs>(args)...);
264   }
265 };
266 
267 // InvokeHelper<>
268 //
269 // There are 2 logical InvokeHelper<> specializations: normal, WeakCalls.
270 //
271 // The normal type just calls the underlying runnable.
272 //
273 // WeakCalls need special syntax that is applied to the first argument to check
274 // if they should no-op themselves.
275 template <bool is_weak_call, typename ReturnType>
276 struct InvokeHelper;
277 
278 template <typename ReturnType>
279 struct InvokeHelper<false, ReturnType> {
280   template <typename Functor, typename... RunArgs>
281   static inline ReturnType MakeItSo(Functor&& functor, RunArgs&&... args) {
282     using Traits = FunctorTraits<typename std::decay<Functor>::type>;
283     return Traits::Invoke(std::forward<Functor>(functor),
284                           std::forward<RunArgs>(args)...);
285   }
286 };
287 
288 template <typename ReturnType>
289 struct InvokeHelper<true, ReturnType> {
290   // WeakCalls are only supported for functions with a void return type.
291   // Otherwise, the function result would be undefined if the the WeakPtr<>
292   // is invalidated.
293   static_assert(std::is_void<ReturnType>::value,
294                 "weak_ptrs can only bind to methods without return values");
295 
296   template <typename Functor, typename BoundWeakPtr, typename... RunArgs>
297   static inline void MakeItSo(Functor&& functor,
298                               BoundWeakPtr&& weak_ptr,
299                               RunArgs&&... args) {
300     if (!weak_ptr)
301       return;
302     using Traits = FunctorTraits<typename std::decay<Functor>::type>;
303     Traits::Invoke(std::forward<Functor>(functor),
304                    std::forward<BoundWeakPtr>(weak_ptr),
305                    std::forward<RunArgs>(args)...);
306   }
307 };
308 
309 // Invoker<>
310 //
311 // See description at the top of the file.
312 template <typename StorageType, typename UnboundRunType>
313 struct Invoker;
314 
315 template <typename StorageType, typename R, typename... UnboundArgs>
316 struct Invoker<StorageType, R(UnboundArgs...)> {
317   static R Run(BindStateBase* base, UnboundArgs&&... unbound_args) {
318     // Local references to make debugger stepping easier. If in a debugger,
319     // you really want to warp ahead and step through the
320     // InvokeHelper<>::MakeItSo() call below.
321     const StorageType* storage = static_cast<StorageType*>(base);
322     static constexpr size_t num_bound_args =
323         std::tuple_size<decltype(storage->bound_args_)>::value;
324     return RunImpl(storage->functor_,
325                    storage->bound_args_,
326                    MakeIndexSequence<num_bound_args>(),
327                    std::forward<UnboundArgs>(unbound_args)...);
328   }
329 
330  private:
331   template <typename Functor, typename BoundArgsTuple, size_t... indices>
332   static inline R RunImpl(Functor&& functor,
333                           BoundArgsTuple&& bound,
334                           IndexSequence<indices...>,
335                           UnboundArgs&&... unbound_args) {
336     static constexpr bool is_method =
337         FunctorTraits<typename std::decay<Functor>::type>::is_method;
338 
339     using DecayedArgsTuple = typename std::decay<BoundArgsTuple>::type;
340     static constexpr bool is_weak_call =
341         IsWeakMethod<is_method,
342                      typename std::tuple_element<
343                          indices,
344                          DecayedArgsTuple>::type...>::value;
345 
346     return InvokeHelper<is_weak_call, R>::MakeItSo(
347         std::forward<Functor>(functor),
348         Unwrap(base::get<indices>(std::forward<BoundArgsTuple>(bound)))...,
349         std::forward<UnboundArgs>(unbound_args)...);
350   }
351 };
352 
353 // Used to implement MakeUnboundRunType.
354 template <typename Functor, typename... BoundArgs>
355 struct MakeUnboundRunTypeImpl {
356   using RunType =
357       typename FunctorTraits<typename std::decay<Functor>::type>::RunType;
358   using ReturnType = ExtractReturnType<RunType>;
359   using Args = ExtractArgs<RunType>;
360   using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), Args>;
361   using Type = MakeFunctionType<ReturnType, UnboundArgs>;
362 };
363 template <typename Functor>
364 typename std::enable_if<FunctorTraits<Functor>::is_nullable, bool>::type
365 IsNull(const Functor& functor) {
366   return !functor;
367 }
368 
369 template <typename Functor>
370 typename std::enable_if<!FunctorTraits<Functor>::is_nullable, bool>::type
371 IsNull(const Functor&) {
372   return false;
373 }
374 
375 // BindState<>
376 //
377 // This stores all the state passed into Bind().
378 template <typename Functor, typename... BoundArgs>
379 struct BindState final : BindStateBase {
380   template <typename ForwardFunctor, typename... ForwardBoundArgs>
381   explicit BindState(ForwardFunctor&& functor, ForwardBoundArgs&&... bound_args)
382       : BindStateBase(&Destroy),
383       functor_(std::forward<ForwardFunctor>(functor)),
384         bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
385     DCHECK(!IsNull(functor_));
386   }
387 
388   Functor functor_;
389   std::tuple<BoundArgs...> bound_args_;
390 
391  private:
392   ~BindState() {}
393 
394   static void Destroy(BindStateBase* self) {
395     delete static_cast<BindState*>(self);
396   }
397 };
398 
399 // Used to implement MakeBindStateType.
400 template <bool is_method, typename Functor, typename... BoundArgs>
401 struct MakeBindStateTypeImpl;
402 
403 template <typename Functor, typename... BoundArgs>
404 struct MakeBindStateTypeImpl<false, Functor, BoundArgs...> {
405   static_assert(!HasRefCountedTypeAsRawPtr<BoundArgs...>::value,
406                 "A parameter is a refcounted type and needs scoped_refptr.");
407   using Type = BindState<typename std::decay<Functor>::type,
408                          typename std::decay<BoundArgs>::type...>;
409 };
410 
411 template <typename Functor>
412 struct MakeBindStateTypeImpl<true, Functor> {
413   using Type = BindState<typename std::decay<Functor>::type>;
414 };
415 
416 template <typename Functor, typename Receiver, typename... BoundArgs>
417 struct MakeBindStateTypeImpl<true, Functor, Receiver, BoundArgs...> {
418   static_assert(
419       !std::is_array<typename std::remove_reference<Receiver>::type>::value,
420       "First bound argument to a method cannot be an array.");
421   static_assert(!HasRefCountedTypeAsRawPtr<BoundArgs...>::value,
422                 "A parameter is a refcounted type and needs scoped_refptr.");
423 
424  private:
425   using DecayedReceiver = typename std::decay<Receiver>::type;
426 
427  public:
428   using Type = BindState<
429       typename std::decay<Functor>::type,
430       typename std::conditional<
431           std::is_pointer<DecayedReceiver>::value,
432           scoped_refptr<typename std::remove_pointer<DecayedReceiver>::type>,
433           DecayedReceiver>::type,
434       typename std::decay<BoundArgs>::type...>;
435 };
436 
437 template <typename Functor, typename... BoundArgs>
438 using MakeBindStateType = typename MakeBindStateTypeImpl<
439     FunctorTraits<typename std::decay<Functor>::type>::is_method,
440     Functor,
441     BoundArgs...>::Type;
442 
443 }  // namespace internal
444 
445 // Returns a RunType of bound functor.
446 // E.g. MakeUnboundRunType<R(A, B, C), A, B> is evaluated to R(C).
447 template <typename Functor, typename... BoundArgs>
448 using MakeUnboundRunType =
449     typename internal::MakeUnboundRunTypeImpl<Functor, BoundArgs...>::Type;
450 
451 }  // namespace base
452 
453 #endif  // BASE_BIND_INTERNAL_H_
454