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 <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 : 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                        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 : 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                        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 : false_type {};
    105 
    106 template <typename T, typename... Args>
    107 struct BindsArrayToFirstArg<true, T, Args...> : 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 = 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 = 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(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