Index: base/bind_internal.h |
diff --git a/base/bind_internal.h b/base/bind_internal.h |
index c7d6c3b4adc5f52e05dabd3bfd2d31e13e2bae84..6b692a85a9d5424231489d964226d38f5b5932da 100644 |
--- a/base/bind_internal.h |
+++ b/base/bind_internal.h |
@@ -18,10 +18,6 @@ |
#include "base/tuple.h" |
#include "build/build_config.h" |
-#if defined(OS_WIN) |
-#include "base/bind_internal_win.h" |
-#endif |
- |
namespace base { |
namespace internal { |
@@ -29,40 +25,26 @@ namespace internal { |
// |
// |
// CONCEPTS: |
-// Runnable -- A type (really a type class) that has a single Run() method |
-// and a RunType typedef that corresponds to the type of Run(). |
-// A Runnable can declare that it should treated like a method |
-// call by including a typedef named IsMethod. The value of |
-// this typedef is NOT inspected, only the existence. When a |
-// Runnable declares itself a method, Bind() will enforce special |
-// refcounting + WeakPtr handling semantics for the first |
-// parameter which is expected to be an object. |
-// Functor -- A copyable type representing something that should be called. |
-// All function pointers, Callback<>, and Runnables are functors |
-// even if the invocation syntax differs. |
+// Functor -- A movable type representing something that should be called. |
+// All function pointers and Callback<> are functors even if the |
+// invocation syntax differs. |
// RunType -- A function type (as opposed to function _pointer_ type) for |
-// a Run() function. Usually just a convenience typedef. |
+// a Callback<>::Run(). Usually just a convenience typedef. |
// (Bound)Args -- A set of types that stores the arguments. |
// |
// Types: |
-// RunnableAdapter<> -- Wraps the various "function" pointer types into an |
-// object that adheres to the Runnable interface. |
// ForceVoidReturn<> -- Helper class for translating function signatures to |
// equivalent forms with a "void" return type. |
-// FunctorTraits<> -- Type traits used determine the correct RunType and |
-// RunnableType for a Functor. This is where function |
+// FunctorTraits<> -- Type traits used to determine the correct RunType and |
+// invocation manner for a Functor. This is where function |
// signature adapters are applied. |
-// MakeRunnable<> -- Takes a Functor and returns an object in the Runnable |
-// type class that represents the underlying Functor. |
-// InvokeHelper<> -- Take a Runnable + arguments and actully invokes it. |
+// InvokeHelper<> -- Take a Functor + arguments and actully invokes it. |
// Handle the differing syntaxes needed for WeakPtr<> |
-// support, and for ignoring return values. This is separate |
-// from Invoker to avoid creating multiple version of |
-// Invoker<>. |
-// Invoker<> -- Unwraps the curried parameters and executes the Runnable. |
+// support. This is separate from Invoker to avoid creating |
+// multiple version of Invoker<>. |
+// Invoker<> -- Unwraps the curried parameters and executes the Functor. |
// BindState<> -- Stores the curried parameters, and is the main entry point |
-// into the Bind() system, doing most of the type resolution. |
-// There are ARITY BindState types. |
+// into the Bind() system. |
// HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw |
// pointer to a RefCounted type. |
@@ -80,239 +62,150 @@ struct HasRefCountedTypeAsRawPtr<T, Args...> |
std::true_type, |
HasRefCountedTypeAsRawPtr<Args...>>::type {}; |
-// BindsArrayToFirstArg selects true_type when |is_method| is true and the first |
-// item of |Args| is an array type. |
-// Implementation note: This non-specialized case handles !is_method case and |
-// zero-arity case only. Other cases should be handled by the specialization |
-// below. |
-template <bool is_method, typename... Args> |
-struct BindsArrayToFirstArg : std::false_type {}; |
- |
-template <typename T, typename... Args> |
-struct BindsArrayToFirstArg<true, T, Args...> |
- : std::is_array<typename std::remove_reference<T>::type> {}; |
- |
-// HasRefCountedParamAsRawPtr is the same to HasRefCountedTypeAsRawPtr except |
-// when |is_method| is true HasRefCountedParamAsRawPtr skips the first argument. |
-// Implementation note: This non-specialized case handles !is_method case and |
-// zero-arity case only. Other cases should be handled by the specialization |
-// below. |
-template <bool is_method, typename... Args> |
-struct HasRefCountedParamAsRawPtr : HasRefCountedTypeAsRawPtr<Args...> {}; |
+// ForceVoidReturn<> |
+// |
+// Set of templates that support forcing the function return type to void. |
+template <typename Sig> |
+struct ForceVoidReturn; |
-template <typename T, typename... Args> |
-struct HasRefCountedParamAsRawPtr<true, T, Args...> |
- : HasRefCountedTypeAsRawPtr<Args...> {}; |
+template <typename R, typename... Args> |
+struct ForceVoidReturn<R(Args...)> { |
+ using RunType = void(Args...); |
+}; |
-// RunnableAdapter<> |
-// |
-// The RunnableAdapter<> templates provide a uniform interface for invoking |
-// a function pointer, method pointer, or const method pointer. The adapter |
-// exposes a Run() method with an appropriate signature. Using this wrapper |
-// allows for writing code that supports all three pointer types without |
-// undue repetition. Without it, a lot of code would need to be repeated 3 |
-// times. |
-// |
-// For method pointers and const method pointers the first argument to Run() |
-// is considered to be the received of the method. This is similar to STL's |
-// mem_fun(). |
-// |
-// This class also exposes a RunType typedef that is the function type of the |
-// Run() function. |
+// FunctorTraits<> |
// |
-// If and only if the wrapper contains a method or const method pointer, an |
-// IsMethod typedef is exposed. The existence of this typedef (NOT the value) |
-// marks that the wrapper should be considered a method wrapper. |
- |
+// See description at top of file. |
template <typename Functor> |
-class RunnableAdapter; |
+struct FunctorTraits; |
-// Function. |
+// For functions. |
template <typename R, typename... Args> |
-class RunnableAdapter<R(*)(Args...)> { |
- public: |
- // MSVC 2013 doesn't support Type Alias of function types. |
- // Revisit this after we update it to newer version. |
- typedef R RunType(Args...); |
+struct FunctorTraits<R (*)(Args...)> { |
+ using RunType = R(Args...); |
+ static constexpr bool is_method = false; |
- explicit RunnableAdapter(R(*function)(Args...)) |
- : function_(function) { |
+ template <typename... RunArgs> |
+ static R Invoke(R (*function)(Args...), RunArgs&&... args) { |
+ return function(std::forward<RunArgs>(args)...); |
} |
+}; |
+ |
+#if defined(OS_WIN) && !defined(ARCH_CPU_X86_64) |
+ |
+// For functions. |
+template <typename R, typename... Args> |
+struct FunctorTraits<R(__stdcall*)(Args...)> { |
+ using RunType = R(Args...); |
+ static constexpr bool is_method = false; |
template <typename... RunArgs> |
- R Run(RunArgs&&... args) const { |
- return function_(std::forward<RunArgs>(args)...); |
+ static R Invoke(R(__stdcall* function)(Args...), RunArgs&&... args) { |
+ return function(std::forward<RunArgs>(args)...); |
} |
- |
- private: |
- R (*function_)(Args...); |
}; |
-// Method. |
-template <typename R, typename T, typename... Args> |
-class RunnableAdapter<R(T::*)(Args...)> { |
- public: |
- // MSVC 2013 doesn't support Type Alias of function types. |
- // Revisit this after we update it to newer version. |
- typedef R RunType(T*, Args...); |
- using IsMethod = std::true_type; |
+// For functions. |
+template <typename R, typename... Args> |
+struct FunctorTraits<R(__fastcall*)(Args...)> { |
+ using RunType = R(Args...); |
+ static constexpr bool is_method = false; |
- explicit RunnableAdapter(R(T::*method)(Args...)) |
- : method_(method) { |
+ template <typename... RunArgs> |
+ static R Invoke(R(__fastcall* function)(Args...), RunArgs&&... args) { |
+ return function(std::forward<RunArgs>(args)...); |
} |
+}; |
+ |
+#endif // defined(OS_WIN) && !defined(ARCH_CPU_X86_64) |
- template <typename Receiver, typename... RunArgs> |
- R Run(Receiver&& receiver_ptr, RunArgs&&... args) const { |
+// For methods. |
+template <typename R, typename Receiver, typename... Args> |
+struct FunctorTraits<R (Receiver::*)(Args...)> { |
+ using RunType = R(Receiver*, Args...); |
+ static constexpr bool is_method = true; |
+ |
+ template <typename ReceiverPtr, typename... RunArgs> |
+ static R Invoke(R (Receiver::*method)(Args...), |
+ ReceiverPtr&& receiver_ptr, |
+ RunArgs&&... args) { |
// Clang skips CV qualifier check on a method pointer invocation when the |
// receiver is a subclass. Store the receiver into a const reference to |
// T to ensure the CV check works. |
// https://llvm.org/bugs/show_bug.cgi?id=27037 |
- T& receiver = *receiver_ptr; |
- return (receiver.*method_)(std::forward<RunArgs>(args)...); |
+ Receiver& receiver = *receiver_ptr; |
+ return (receiver.*method)(std::forward<RunArgs>(args)...); |
} |
- |
- private: |
- R (T::*method_)(Args...); |
}; |
-// Const Method. |
-template <typename R, typename T, typename... Args> |
-class RunnableAdapter<R(T::*)(Args...) const> { |
- public: |
- using RunType = R(const T*, Args...); |
- using IsMethod = std::true_type; |
- |
- explicit RunnableAdapter(R(T::*method)(Args...) const) |
- : method_(method) { |
- } |
+// For const methods. |
+template <typename R, typename Receiver, typename... Args> |
+struct FunctorTraits<R (Receiver::*)(Args...) const> { |
+ using RunType = R(const Receiver*, Args...); |
+ static constexpr bool is_method = true; |
- template <typename Receiver, typename... RunArgs> |
- R Run(Receiver&& receiver_ptr, RunArgs&&... args) const { |
+ template <typename ReceiverPtr, typename... RunArgs> |
+ static R Invoke(R (Receiver::*method)(Args...) const, |
+ ReceiverPtr&& receiver_ptr, |
+ RunArgs&&... args) { |
// Clang skips CV qualifier check on a method pointer invocation when the |
- // receiver is a subclass. Store the receiver into a unqualified reference |
- // to T to ensure the CV check works. |
+ // receiver is a subclass. Store the receiver into a const reference to |
+ // T to ensure the CV check works. |
// https://llvm.org/bugs/show_bug.cgi?id=27037 |
- const T& receiver = *receiver_ptr; |
- return (receiver.*method_)(std::forward<RunArgs>(args)...); |
+ const Receiver& receiver = *receiver_ptr; |
+ return (receiver.*method)(std::forward<RunArgs>(args)...); |
} |
- |
- private: |
- R (T::*method_)(Args...) const; |
}; |
- |
-// ForceVoidReturn<> |
-// |
-// Set of templates that support forcing the function return type to void. |
-template <typename Sig> |
-struct ForceVoidReturn; |
- |
-template <typename R, typename... Args> |
-struct ForceVoidReturn<R(Args...)> { |
- // MSVC 2013 doesn't support Type Alias of function types. |
- // Revisit this after we update it to newer version. |
- typedef void RunType(Args...); |
-}; |
- |
- |
-// FunctorTraits<> |
-// |
-// See description at top of file. |
+// For IgnoreResults. |
template <typename T> |
-struct FunctorTraits { |
- using RunnableType = RunnableAdapter<T>; |
- using RunType = typename RunnableType::RunType; |
-}; |
- |
-template <typename T> |
-struct FunctorTraits<IgnoreResultHelper<T>> { |
- using RunnableType = typename FunctorTraits<T>::RunnableType; |
+struct FunctorTraits<IgnoreResultHelper<T>> : FunctorTraits<T> { |
using RunType = |
- typename ForceVoidReturn<typename RunnableType::RunType>::RunType; |
-}; |
+ typename ForceVoidReturn<typename FunctorTraits<T>::RunType>::RunType; |
-template <typename T> |
-struct FunctorTraits<Callback<T>> { |
- using RunnableType = Callback<T> ; |
- using RunType = typename Callback<T>::RunType; |
+ template <typename IgnoreResultType, typename... RunArgs> |
+ static void Invoke(IgnoreResultType&& ignore_result_helper, |
+ RunArgs&&... args) { |
+ FunctorTraits<T>::Invoke(ignore_result_helper.functor_, |
+ std::forward<RunArgs>(args)...); |
+ } |
}; |
- |
-// MakeRunnable<> |
-// |
-// Converts a passed in functor to a RunnableType using type inference. |
- |
-template <typename T> |
-typename FunctorTraits<T>::RunnableType MakeRunnable(const T& t) { |
- return RunnableAdapter<T>(t); |
-} |
- |
-template <typename T> |
-typename FunctorTraits<T>::RunnableType |
-MakeRunnable(const IgnoreResultHelper<T>& t) { |
- return MakeRunnable(t.functor_); |
-} |
- |
-template <typename T> |
-const typename FunctorTraits<Callback<T>>::RunnableType& |
-MakeRunnable(const Callback<T>& t) { |
- DCHECK(!t.is_null()); |
- return t; |
-} |
- |
+// For Callbacks. |
+template <typename R, typename... Args, CopyMode copy_mode> |
+struct FunctorTraits<Callback<R(Args...), copy_mode>> { |
+ using RunType = R(Args...); |
+ static constexpr bool is_method = false; |
+ |
+ template <typename CallbackType, typename... RunArgs> |
+ static R Invoke(CallbackType&& callback, RunArgs&&... args) { |
+ DCHECK(!callback.is_null()); |
+ return std::forward<CallbackType>(callback).Run( |
+ std::forward<RunArgs>(args)...); |
+ } |
+}; |
// InvokeHelper<> |
// |
-// There are 3 logical InvokeHelper<> specializations: normal, void-return, |
-// WeakCalls. |
+// There are 2 logical InvokeHelper<> specializations: normal, WeakCalls. |
// |
// The normal type just calls the underlying runnable. |
// |
-// We need a InvokeHelper to handle void return types in order to support |
-// IgnoreResult(). Normally, if the Runnable's RunType had a void return, |
-// the template system would just accept "return functor.Run()" ignoring |
-// the fact that a void function is being used with return. This piece of |
-// sugar breaks though when the Runnable's RunType is not void. Thus, we |
-// need a partial specialization to change the syntax to drop the "return" |
-// from the invocation call. |
-// |
-// WeakCalls similarly need special syntax that is applied to the first |
-// argument to check if they should no-op themselves. |
+// WeakCalls need special syntax that is applied to the first argument to check |
+// if they should no-op themselves. |
template <bool is_weak_call, typename ReturnType> |
struct InvokeHelper; |
template <typename ReturnType> |
struct InvokeHelper<false, ReturnType> { |
- template <typename Runnable, typename... RunArgs> |
- static inline ReturnType MakeItSo(Runnable&& runnable, RunArgs&&... args) { |
- return std::forward<Runnable>(runnable).Run(std::forward<RunArgs>(args)...); |
- } |
-}; |
- |
-template <> |
-struct InvokeHelper<false, void> { |
- template <typename Runnable, typename... RunArgs> |
- static inline void MakeItSo(Runnable&& runnable, RunArgs&&... args) { |
- std::forward<Runnable>(runnable).Run(std::forward<RunArgs>(args)...); |
- } |
-}; |
- |
-template <> |
-struct InvokeHelper<true, void> { |
- template <typename Runnable, typename BoundWeakPtr, typename... RunArgs> |
- static void MakeItSo(Runnable&& runnable, |
- BoundWeakPtr&& weak_ptr, |
- RunArgs&&... args) { |
- if (!weak_ptr) { |
- return; |
- } |
- std::forward<Runnable>(runnable).Run( |
- std::forward<BoundWeakPtr>(weak_ptr), std::forward<RunArgs>(args)...); |
+ template <typename Functor, typename... RunArgs> |
+ static inline ReturnType MakeItSo(Functor&& functor, RunArgs&&... args) { |
+ using Traits = FunctorTraits<typename std::decay<Functor>::type>; |
+ return Traits::Invoke(std::forward<Functor>(functor), |
+ std::forward<RunArgs>(args)...); |
} |
}; |
-#if !defined(_MSC_VER) |
- |
template <typename ReturnType> |
struct InvokeHelper<true, ReturnType> { |
// WeakCalls are only supported for functions with a void return type. |
@@ -320,9 +213,19 @@ struct InvokeHelper<true, ReturnType> { |
// is invalidated. |
static_assert(std::is_void<ReturnType>::value, |
"weak_ptrs can only bind to methods without return values"); |
-}; |
-#endif |
+ template <typename Functor, typename BoundWeakPtr, typename... RunArgs> |
+ static inline void MakeItSo(Functor&& functor, |
+ BoundWeakPtr weak_ptr, |
+ RunArgs&&... args) { |
+ if (!weak_ptr) |
+ return; |
+ using Traits = FunctorTraits<typename std::decay<Functor>::type>; |
+ Traits::Invoke(std::forward<Functor>(functor), |
+ std::forward<BoundWeakPtr>(weak_ptr), |
+ std::forward<RunArgs>(args)...); |
+ } |
+}; |
// Invoker<> |
// |
@@ -339,19 +242,20 @@ struct Invoker<StorageType, R(UnboundArgs...)> { |
const StorageType* storage = static_cast<StorageType*>(base); |
static constexpr size_t num_bound_args = |
std::tuple_size<decltype(storage->bound_args_)>::value; |
- return RunImpl(storage->runnable_, |
+ return RunImpl(storage->functor_, |
storage->bound_args_, |
MakeIndexSequence<num_bound_args>(), |
std::forward<UnboundArgs>(unbound_args)...); |
} |
- template <typename Runnable, typename BoundArgsTuple, size_t... indices> |
- static inline R RunImpl(Runnable&& runnable, |
+ private: |
+ template <typename Functor, typename BoundArgsTuple, size_t... indices> |
+ static inline R RunImpl(Functor&& functor, |
BoundArgsTuple&& bound, |
IndexSequence<indices...>, |
UnboundArgs&&... unbound_args) { |
static constexpr bool is_method = |
- HasIsMethodTag<typename std::decay<Runnable>::type>::value; |
+ FunctorTraits<typename std::decay<Functor>::type>::is_method; |
using DecayedArgsTuple = typename std::decay<BoundArgsTuple>::type; |
static constexpr bool is_weak_call = |
@@ -361,35 +265,17 @@ struct Invoker<StorageType, R(UnboundArgs...)> { |
DecayedArgsTuple>::type...>::value; |
return InvokeHelper<is_weak_call, R>::MakeItSo( |
- std::forward<Runnable>(runnable), |
- Unwrap(std::get<indices>(std::forward<BoundArgsTuple>(bound)))..., |
+ std::forward<Functor>(functor), |
+ Unwrap(base::get<indices>(std::forward<BoundArgsTuple>(bound)))..., |
std::forward<UnboundArgs>(unbound_args)...); |
} |
}; |
-// Used to implement MakeArgsStorage. |
-template <bool is_method, typename... BoundArgs> |
-struct MakeArgsStorageImpl { |
- using Type = std::tuple<BoundArgs...>; |
-}; |
- |
-template <typename Obj, typename... BoundArgs> |
-struct MakeArgsStorageImpl<true, Obj*, BoundArgs...> { |
- using Type = std::tuple<scoped_refptr<Obj>, BoundArgs...>; |
-}; |
- |
-// Constructs a tuple type to store BoundArgs into BindState. |
-// This wraps the first argument into a scoped_refptr if |is_method| is true and |
-// the first argument is a raw pointer. |
-// Other arguments are adjusted for store and packed into a tuple. |
-template <bool is_method, typename... BoundArgs> |
-using MakeArgsStorage = typename MakeArgsStorageImpl< |
- is_method, typename std::decay<BoundArgs>::type...>::Type; |
- |
// Used to implement MakeUnboundRunType. |
template <typename Functor, typename... BoundArgs> |
struct MakeUnboundRunTypeImpl { |
- using RunType = typename FunctorTraits<Functor>::RunType; |
+ using RunType = |
+ typename FunctorTraits<typename std::decay<Functor>::type>::RunType; |
using ReturnType = ExtractReturnType<RunType>; |
using Args = ExtractArgs<RunType>; |
using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), Args>; |
@@ -398,28 +284,19 @@ struct MakeUnboundRunTypeImpl { |
// BindState<> |
// |
-// This stores all the state passed into Bind() and is also where most |
-// of the template resolution magic occurs. |
-// |
-// Runnable is the functor we are binding arguments to. |
-// |
-// BoundArgs contains the storage type for all the bound arguments. |
-template <typename Runnable, typename... BoundArgs> |
-struct BindState final : public BindStateBase { |
- private: |
- using RunnableType = typename std::decay<Runnable>::type; |
- |
- static constexpr bool is_method = HasIsMethodTag<RunnableType>::value; |
- |
- public: |
- template <typename... ForwardArgs> |
- explicit BindState(RunnableType runnable, ForwardArgs&&... bound_args) |
+// This stores all the state passed into Bind(). |
+template <typename Functor, typename... BoundArgs> |
+struct BindState final : BindStateBase { |
+ template <typename... ForwardBoundArgs> |
+ explicit BindState(Functor functor, ForwardBoundArgs&&... bound_args) |
: BindStateBase(&Destroy), |
- runnable_(std::move(runnable)), |
- bound_args_(std::forward<ForwardArgs>(bound_args)...) {} |
+ functor_(std::move(functor)), |
+ bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) { |
+ DCHECK(functor_); |
+ } |
- RunnableType runnable_; |
- MakeArgsStorage<is_method, BoundArgs...> bound_args_; |
+ Functor functor_; |
+ std::tuple<BoundArgs...> bound_args_; |
private: |
~BindState() {} |
@@ -429,6 +306,50 @@ struct BindState final : public BindStateBase { |
} |
}; |
+// Used to implement MakeBindStateType. |
+template <bool is_method, typename Functor, typename... BoundArgs> |
+struct MakeBindStateTypeImpl; |
+ |
+template <typename Functor, typename... BoundArgs> |
+struct MakeBindStateTypeImpl<false, Functor, BoundArgs...> { |
+ static_assert(!HasRefCountedTypeAsRawPtr<BoundArgs...>::value, |
+ "A parameter is a refcounted type and needs scoped_refptr."); |
+ using Type = BindState<typename std::decay<Functor>::type, |
+ typename std::decay<BoundArgs>::type...>; |
+}; |
+ |
+template <typename Functor> |
+struct MakeBindStateTypeImpl<true, Functor> { |
+ using Type = BindState<typename std::decay<Functor>::type>; |
+}; |
+ |
+template <typename Functor, typename Receiver, typename... BoundArgs> |
+struct MakeBindStateTypeImpl<true, Functor, Receiver, BoundArgs...> { |
+ static_assert( |
+ !std::is_array<typename std::remove_reference<Receiver>::type>::value, |
+ "First bound argument to a method cannot be an array."); |
+ static_assert(!HasRefCountedTypeAsRawPtr<BoundArgs...>::value, |
+ "A parameter is a refcounted type and needs scoped_refptr."); |
+ |
+ private: |
+ using DecayedReceiver = typename std::decay<Receiver>::type; |
+ |
+ public: |
+ using Type = BindState< |
+ typename std::decay<Functor>::type, |
+ typename std::conditional< |
+ std::is_pointer<DecayedReceiver>::value, |
+ scoped_refptr<typename std::remove_pointer<DecayedReceiver>::type>, |
+ DecayedReceiver>::type, |
+ typename std::decay<BoundArgs>::type...>; |
+}; |
+ |
+template <typename Functor, typename... BoundArgs> |
+using MakeBindStateType = typename MakeBindStateTypeImpl< |
+ FunctorTraits<typename std::decay<Functor>::type>::is_method, |
+ Functor, |
+ BoundArgs...>::Type; |
+ |
} // namespace internal |
// Returns a RunType of bound functor. |