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>
    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(
    248         std::forward<IgnoreResultType>(ignore_result_helper).functor_,
    249         std::forward<RunArgs>(args)...);
    250   }
    251 };
    252 
    253 // For Callbacks.
    254 template <typename R, typename... Args,
    255           CopyMode copy_mode, RepeatMode repeat_mode>
    256 struct FunctorTraits<Callback<R(Args...), copy_mode, repeat_mode>> {
    257   using RunType = R(Args...);
    258   static constexpr bool is_method = false;
    259   static constexpr bool is_nullable = true;
    260 
    261   template <typename CallbackType, typename... RunArgs>
    262   static R Invoke(CallbackType&& callback, RunArgs&&... args) {
    263     DCHECK(!callback.is_null());
    264     return std::forward<CallbackType>(callback).Run(
    265         std::forward<RunArgs>(args)...);
    266   }
    267 };
    268 
    269 // InvokeHelper<>
    270 //
    271 // There are 2 logical InvokeHelper<> specializations: normal, WeakCalls.
    272 //
    273 // The normal type just calls the underlying runnable.
    274 //
    275 // WeakCalls need special syntax that is applied to the first argument to check
    276 // if they should no-op themselves.
    277 template <bool is_weak_call, typename ReturnType>
    278 struct InvokeHelper;
    279 
    280 template <typename ReturnType>
    281 struct InvokeHelper<false, ReturnType> {
    282   template <typename Functor, typename... RunArgs>
    283   static inline ReturnType MakeItSo(Functor&& functor, RunArgs&&... args) {
    284     using Traits = FunctorTraits<typename std::decay<Functor>::type>;
    285     return Traits::Invoke(std::forward<Functor>(functor),
    286                           std::forward<RunArgs>(args)...);
    287   }
    288 };
    289 
    290 template <typename ReturnType>
    291 struct InvokeHelper<true, ReturnType> {
    292   // WeakCalls are only supported for functions with a void return type.
    293   // Otherwise, the function result would be undefined if the the WeakPtr<>
    294   // is invalidated.
    295   static_assert(std::is_void<ReturnType>::value,
    296                 "weak_ptrs can only bind to methods without return values");
    297 
    298   template <typename Functor, typename BoundWeakPtr, typename... RunArgs>
    299   static inline void MakeItSo(Functor&& functor,
    300                               BoundWeakPtr&& weak_ptr,
    301                               RunArgs&&... args) {
    302     if (!weak_ptr)
    303       return;
    304     using Traits = FunctorTraits<typename std::decay<Functor>::type>;
    305     Traits::Invoke(std::forward<Functor>(functor),
    306                    std::forward<BoundWeakPtr>(weak_ptr),
    307                    std::forward<RunArgs>(args)...);
    308   }
    309 };
    310 
    311 // Invoker<>
    312 //
    313 // See description at the top of the file.
    314 template <typename StorageType, typename UnboundRunType>
    315 struct Invoker;
    316 
    317 template <typename StorageType, typename R, typename... UnboundArgs>
    318 struct Invoker<StorageType, R(UnboundArgs...)> {
    319   static R RunOnce(BindStateBase* base, UnboundArgs&&... unbound_args) {
    320     // Local references to make debugger stepping easier. If in a debugger,
    321     // you really want to warp ahead and step through the
    322     // InvokeHelper<>::MakeItSo() call below.
    323     StorageType* storage = static_cast<StorageType*>(base);
    324     static constexpr size_t num_bound_args =
    325         std::tuple_size<decltype(storage->bound_args_)>::value;
    326     return RunImpl(std::move(storage->functor_),
    327                    std::move(storage->bound_args_),
    328                    MakeIndexSequence<num_bound_args>(),
    329                    std::forward<UnboundArgs>(unbound_args)...);
    330   }
    331 
    332   static R Run(BindStateBase* base, UnboundArgs&&... unbound_args) {
    333     // Local references to make debugger stepping easier. If in a debugger,
    334     // you really want to warp ahead and step through the
    335     // InvokeHelper<>::MakeItSo() call below.
    336     const StorageType* storage = static_cast<StorageType*>(base);
    337     static constexpr size_t num_bound_args =
    338         std::tuple_size<decltype(storage->bound_args_)>::value;
    339     return RunImpl(storage->functor_,
    340                    storage->bound_args_,
    341                    MakeIndexSequence<num_bound_args>(),
    342                    std::forward<UnboundArgs>(unbound_args)...);
    343   }
    344 
    345  private:
    346   template <typename Functor, typename BoundArgsTuple, size_t... indices>
    347   static inline R RunImpl(Functor&& functor,
    348                           BoundArgsTuple&& bound,
    349                           IndexSequence<indices...>,
    350                           UnboundArgs&&... unbound_args) {
    351     static constexpr bool is_method =
    352         FunctorTraits<typename std::decay<Functor>::type>::is_method;
    353 
    354     using DecayedArgsTuple = typename std::decay<BoundArgsTuple>::type;
    355     static constexpr bool is_weak_call =
    356         IsWeakMethod<is_method,
    357                      typename std::tuple_element<
    358                          indices,
    359                          DecayedArgsTuple>::type...>::value;
    360 
    361     return InvokeHelper<is_weak_call, R>::MakeItSo(
    362         std::forward<Functor>(functor),
    363         Unwrap(base::get<indices>(std::forward<BoundArgsTuple>(bound)))...,
    364         std::forward<UnboundArgs>(unbound_args)...);
    365   }
    366 };
    367 
    368 // Used to implement MakeUnboundRunType.
    369 template <typename Functor, typename... BoundArgs>
    370 struct MakeUnboundRunTypeImpl {
    371   using RunType =
    372       typename FunctorTraits<typename std::decay<Functor>::type>::RunType;
    373   using ReturnType = ExtractReturnType<RunType>;
    374   using Args = ExtractArgs<RunType>;
    375   using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), Args>;
    376   using Type = MakeFunctionType<ReturnType, UnboundArgs>;
    377 };
    378 template <typename Functor>
    379 typename std::enable_if<FunctorTraits<Functor>::is_nullable, bool>::type
    380 IsNull(const Functor& functor) {
    381   return !functor;
    382 }
    383 
    384 template <typename Functor>
    385 typename std::enable_if<!FunctorTraits<Functor>::is_nullable, bool>::type
    386 IsNull(const Functor&) {
    387   return false;
    388 }
    389 
    390 // Used by ApplyCancellationTraits below.
    391 template <typename Functor, typename BoundArgsTuple, size_t... indices>
    392 bool ApplyCancellationTraitsImpl(const Functor& functor,
    393                                  const BoundArgsTuple& bound_args,
    394                                  IndexSequence<indices...>) {
    395   return CallbackCancellationTraits<Functor, BoundArgsTuple>::IsCancelled(
    396       functor, base::get<indices>(bound_args)...);
    397 }
    398 
    399 // Relays |base| to corresponding CallbackCancellationTraits<>::Run(). Returns
    400 // true if the callback |base| represents is canceled.
    401 template <typename BindStateType>
    402 bool ApplyCancellationTraits(const BindStateBase* base) {
    403   const BindStateType* storage = static_cast<const BindStateType*>(base);
    404   static constexpr size_t num_bound_args =
    405       std::tuple_size<decltype(storage->bound_args_)>::value;
    406   return ApplyCancellationTraitsImpl(storage->functor_, storage->bound_args_,
    407                                      MakeIndexSequence<num_bound_args>());
    408 };
    409 
    410 // Template helpers to detect using Bind() on a base::Callback without any
    411 // additional arguments. In that case, the original base::Callback object should
    412 // just be directly used.
    413 template <typename Functor, typename... BoundArgs>
    414 struct BindingCallbackWithNoArgs {
    415   static constexpr bool value = false;
    416 };
    417 
    418 template <typename Signature,
    419           typename... BoundArgs,
    420           CopyMode copy_mode,
    421           RepeatMode repeat_mode>
    422 struct BindingCallbackWithNoArgs<Callback<Signature, copy_mode, repeat_mode>,
    423                                  BoundArgs...> {
    424   static constexpr bool value = sizeof...(BoundArgs) == 0;
    425 };
    426 
    427 // BindState<>
    428 //
    429 // This stores all the state passed into Bind().
    430 template <typename Functor, typename... BoundArgs>
    431 struct BindState final : BindStateBase {
    432   using IsCancellable = std::integral_constant<
    433       bool,
    434       CallbackCancellationTraits<Functor,
    435                                  std::tuple<BoundArgs...>>::is_cancellable>;
    436 
    437   template <typename ForwardFunctor, typename... ForwardBoundArgs>
    438   explicit BindState(BindStateBase::InvokeFuncStorage invoke_func,
    439                      ForwardFunctor&& functor,
    440                      ForwardBoundArgs&&... bound_args)
    441       // IsCancellable is std::false_type if
    442       // CallbackCancellationTraits<>::IsCancelled returns always false.
    443       // Otherwise, it's std::true_type.
    444       : BindState(IsCancellable{},
    445                   invoke_func,
    446                   std::forward<ForwardFunctor>(functor),
    447                   std::forward<ForwardBoundArgs>(bound_args)...) {
    448     static_assert(!BindingCallbackWithNoArgs<Functor, BoundArgs...>::value,
    449                   "Attempting to bind a base::Callback with no additional "
    450                   "arguments: save a heap allocation and use the original "
    451                   "base::Callback object");
    452   }
    453 
    454   Functor functor_;
    455   std::tuple<BoundArgs...> bound_args_;
    456 
    457  private:
    458   template <typename ForwardFunctor, typename... ForwardBoundArgs>
    459   explicit BindState(std::true_type,
    460                      BindStateBase::InvokeFuncStorage invoke_func,
    461                      ForwardFunctor&& functor,
    462                      ForwardBoundArgs&&... bound_args)
    463       : BindStateBase(invoke_func,
    464                       &Destroy,
    465                       &ApplyCancellationTraits<BindState>),
    466         functor_(std::forward<ForwardFunctor>(functor)),
    467         bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
    468     DCHECK(!IsNull(functor_));
    469   }
    470 
    471   template <typename ForwardFunctor, typename... ForwardBoundArgs>
    472   explicit BindState(std::false_type,
    473                      BindStateBase::InvokeFuncStorage invoke_func,
    474                      ForwardFunctor&& functor,
    475                      ForwardBoundArgs&&... bound_args)
    476       : BindStateBase(invoke_func, &Destroy),
    477         functor_(std::forward<ForwardFunctor>(functor)),
    478         bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
    479     DCHECK(!IsNull(functor_));
    480   }
    481 
    482   ~BindState() {}
    483 
    484   static void Destroy(const BindStateBase* self) {
    485     delete static_cast<const BindState*>(self);
    486   }
    487 };
    488 
    489 // Used to implement MakeBindStateType.
    490 template <bool is_method, typename Functor, typename... BoundArgs>
    491 struct MakeBindStateTypeImpl;
    492 
    493 template <typename Functor, typename... BoundArgs>
    494 struct MakeBindStateTypeImpl<false, Functor, BoundArgs...> {
    495   static_assert(!HasRefCountedTypeAsRawPtr<BoundArgs...>::value,
    496                 "A parameter is a refcounted type and needs scoped_refptr.");
    497   using Type = BindState<typename std::decay<Functor>::type,
    498                          typename std::decay<BoundArgs>::type...>;
    499 };
    500 
    501 template <typename Functor>
    502 struct MakeBindStateTypeImpl<true, Functor> {
    503   using Type = BindState<typename std::decay<Functor>::type>;
    504 };
    505 
    506 template <typename Functor, typename Receiver, typename... BoundArgs>
    507 struct MakeBindStateTypeImpl<true, Functor, Receiver, BoundArgs...> {
    508   static_assert(
    509       !std::is_array<typename std::remove_reference<Receiver>::type>::value,
    510       "First bound argument to a method cannot be an array.");
    511   static_assert(!HasRefCountedTypeAsRawPtr<BoundArgs...>::value,
    512                 "A parameter is a refcounted type and needs scoped_refptr.");
    513 
    514  private:
    515   using DecayedReceiver = typename std::decay<Receiver>::type;
    516 
    517  public:
    518   using Type = BindState<
    519       typename std::decay<Functor>::type,
    520       typename std::conditional<
    521           std::is_pointer<DecayedReceiver>::value,
    522           scoped_refptr<typename std::remove_pointer<DecayedReceiver>::type>,
    523           DecayedReceiver>::type,
    524       typename std::decay<BoundArgs>::type...>;
    525 };
    526 
    527 template <typename Functor, typename... BoundArgs>
    528 using MakeBindStateType = typename MakeBindStateTypeImpl<
    529     FunctorTraits<typename std::decay<Functor>::type>::is_method,
    530     Functor,
    531     BoundArgs...>::Type;
    532 
    533 }  // namespace internal
    534 
    535 // Returns a RunType of bound functor.
    536 // E.g. MakeUnboundRunType<R(A, B, C), A, B> is evaluated to R(C).
    537 template <typename Functor, typename... BoundArgs>
    538 using MakeUnboundRunType =
    539     typename internal::MakeUnboundRunTypeImpl<Functor, BoundArgs...>::Type;
    540 
    541 }  // namespace base
    542 
    543 #endif  // BASE_BIND_INTERNAL_H_
    544