Home | History | Annotate | Download | only in base
      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