Decouple Invoker from BindState
Move most of type-level logic out of BindState, and decouple Invoker
from BindState. So that we can use BindState with another Invoker impl.
- UnboundRunType calculation is moved to a separate helper template as
MakeUnboundRuntype.
- Indices generation to extract tuple is moved from BindState to
Invoker.
- WeakPtr handling is moved from BindState to Invoker.
This is a preparation CL as well to implement a OneShot variant of
Callback. That will share the same Callback and BindState impl with
different Invoker::Run impl and different Callback tag as Copyable
Callback and MoveOnly Callback have.
BUG=554299
Review-Url: https://codereview.chromium.org/2034633002
Cr-Commit-Position: refs/heads/master@{#402446}
CrOS-Libchrome-Original-Commit: caf1d84bb83aaf5369eb508027a685e2bf9859b4
diff --git a/base/bind_internal.h b/base/bind_internal.h
index 0107efc..077c0e4 100644
--- a/base/bind_internal.h
+++ b/base/bind_internal.h
@@ -300,7 +300,7 @@
template <typename ReturnType>
struct InvokeHelper<false, ReturnType> {
template <typename Runnable, typename... RunArgs>
- static ReturnType MakeItSo(Runnable&& runnable, RunArgs&&... args) {
+ static inline ReturnType MakeItSo(Runnable&& runnable, RunArgs&&... args) {
return std::forward<Runnable>(runnable).Run(std::forward<RunArgs>(args)...);
}
};
@@ -308,7 +308,7 @@
template <>
struct InvokeHelper<false, void> {
template <typename Runnable, typename... RunArgs>
- static void MakeItSo(Runnable&& runnable, RunArgs&&... args) {
+ static inline void MakeItSo(Runnable&& runnable, RunArgs&&... args) {
std::forward<Runnable>(runnable).Run(std::forward<RunArgs>(args)...);
}
};
@@ -343,27 +343,42 @@
// Invoker<>
//
// See description at the top of the file.
-template <typename BoundIndices, typename StorageType,
- bool is_weak_call, typename UnboundForwardRunType>
+template <typename StorageType, typename UnboundRunType>
struct Invoker;
-template <size_t... bound_indices,
- typename StorageType,
- bool is_weak_call,
- typename R,
- typename... UnboundArgs>
-struct Invoker<IndexSequence<bound_indices...>,
- StorageType,
- is_weak_call,
- R(UnboundArgs...)> {
+template <typename StorageType, typename R, typename... UnboundArgs>
+struct Invoker<StorageType, R(UnboundArgs...)> {
static R Run(BindStateBase* base, UnboundArgs&&... unbound_args) {
- const StorageType* storage = static_cast<StorageType*>(base);
// Local references to make debugger stepping easier. If in a debugger,
// you really want to warp ahead and step through the
// InvokeHelper<>::MakeItSo() call below.
+ 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_,
+ 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,
+ BoundArgsTuple&& bound,
+ IndexSequence<indices...>,
+ UnboundArgs&&... unbound_args) {
+ static constexpr bool is_method =
+ HasIsMethodTag<typename std::decay<Runnable>::type>::value;
+
+ using DecayedArgsTuple = typename std::decay<BoundArgsTuple>::type;
+ static constexpr bool is_weak_call =
+ IsWeakMethod<is_method,
+ typename std::tuple_element<
+ indices,
+ DecayedArgsTuple>::type...>::value;
+
return InvokeHelper<is_weak_call, R>::MakeItSo(
- storage->runnable_,
- Unwrap(std::get<bound_indices>(storage->bound_args_))...,
+ std::forward<Runnable>(runnable),
+ Unwrap(std::get<indices>(std::forward<BoundArgsTuple>(bound)))...,
std::forward<UnboundArgs>(unbound_args)...);
}
};
@@ -387,44 +402,34 @@
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 ReturnType = ExtractReturnType<RunType>;
+ using Args = ExtractArgs<RunType>;
+ using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), Args>;
+ using Type = MakeFunctionType<ReturnType, UnboundArgs>;
+};
+
// 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.
-// RunType is type of the Run() function that the Invoker<> should use.
-// Normally, this is the same as the RunType of the Runnable, but it can
-// be different if an adapter like IgnoreResult() has been used.
//
// BoundArgs contains the storage type for all the bound arguments.
-template <typename Runnable, typename RunType, typename... BoundArgs>
-struct BindState;
-
-template <typename Runnable,
- typename R,
- typename... Args,
- typename... BoundArgs>
-struct BindState<Runnable, R(Args...), BoundArgs...> final
- : public BindStateBase {
+template <typename Runnable, typename... BoundArgs>
+struct BindState final : public BindStateBase {
private:
- using StorageType = BindState<Runnable, R(Args...), BoundArgs...>;
using RunnableType = typename std::decay<Runnable>::type;
- enum { is_method = HasIsMethodTag<RunnableType>::value };
- enum { is_weak_call = IsWeakMethod<
- is_method, typename std::decay<BoundArgs>::type...>::value};
-
- using BoundIndices = MakeIndexSequence<sizeof...(BoundArgs)>;
- using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), TypeList<Args...>>;
+ static constexpr bool is_method = HasIsMethodTag<RunnableType>::value;
public:
- using UnboundRunType = MakeFunctionType<R, UnboundArgs>;
- using InvokerType =
- Invoker<BoundIndices, StorageType, is_weak_call, UnboundRunType>;
-
template <typename... ForwardArgs>
- BindState(RunnableType runnable, ForwardArgs&&... bound_args)
+ explicit BindState(RunnableType runnable, ForwardArgs&&... bound_args)
: BindStateBase(&Destroy),
runnable_(std::move(runnable)),
bound_args_(std::forward<ForwardArgs>(bound_args)...) {}
@@ -441,6 +446,13 @@
};
} // namespace internal
+
+// Returns a RunType of bound functor.
+// E.g. MakeUnboundRunType<R(A, B, C), A, B> is evaluated to R(C).
+template <typename Functor, typename... BoundArgs>
+using MakeUnboundRunType =
+ typename internal::MakeUnboundRunTypeImpl<Functor, BoundArgs...>::Type;
+
} // namespace base
#endif // BASE_BIND_INTERNAL_H_