Document of bind_internal.h in mojo
有关用户文档,请参见base/callback.h。
概念:
————————–
O Runnable — 这个类型(实际上是类型类, type class)具有单个Run()方法,以及对应于Run()的类型的RunType typedef。
Runnable可以通过包含名为IsMethod的typedef来声明它应该被视为方法调用。
该类型函数的值不会被检查,只检查存在的值。
当Runnable声明自己是一个方法时,Bind()将对预期是对象类型的第一个参数强制执行特殊的refcount+WeakPtr处理语义。
O Functor — 一个可复制的类型,表示某个应该被调用的东西。
即使调用语法不同,所有函数指针、Callback<>和Runnables都是仿函数(functor)。
O RunType — Run()函数的函数类型(与函数*指针*类型相反)。
通常只是一种方便的typedef。
O (Bound)ArgsType — 用于存储一组参数的类型的函数类型。
“return”类型在此处始终为void。
使用这种方法,这样我们就不需要为每个类型指定一个新的类型名称。(例如,BindState1、BindState2)。这使得向前声明和友元(Friending)变得容易得多。
类型:
————————–
O RunnableAdapter<> — 将各种“函数”指针类型封装到一个依附于Runnable接口的对象中。
O ForceVoidReturn<> — Helper类,用于将函数特征转换为具有“void”返回类型的等效形式。
O FunctorTraits<> — 使用的类型特征确定仿函数的正确RunType和RunnableType。这是应用函数特征适配器的地方。
O MakeRunnable<> — 接受一个仿函数,并在Runnable类型类中返回一个表示底层仿函数的对象。有|O(1)|的MakeRunnable类型。
O invokeHelper<> — 采用runnable+参数并实际调用它。
处理WeakPtr<>支持和忽略返回值所需的不同语法。这与调用程序是分开的,以避免创建多个版本的Callback<>。
O Invoker<> — 解包curried参数并执行Runnable。
O BindState<> — 存储已绑定的参数,并作为Bind()系统的主要入口点,执行大部分类型解析。存在多个BindState类型。
当|Sig|中的任何参数为非常量引用时,HasNonConstReferenceParam选择true_type。
实例时请注意:此非特化情况仅能处理zero-arity案例。
非zero-arity情况应由以下特化处理。
—————————
实际代码
template <typename Sig>
struct HasNonConstReferenceParam : false_type {};
实现注意:如果第一个参数是非const引用,则选择true_type。否则,跳过第一个参数并递归地检查其余的参数。
template <typename R, typename T, typename... Args>
struct HasNonConstReferenceParam<R(T, Args...)>
: SelectType<is_non_const_reference<T>::value,
true_type,
HasNonConstReferenceParam<R(Args...)>>::Type {};
当|ARGS|中的任何一个是指向RefCounted类型的原始指针时,HasRefCountedTypeAsRawPtr选择true_type。
实施注意:此非特化案例仅处理zero-arity的情况。
非zero-arity的情况应由以下特化处理。
template <typename... Args>
struct HasRefCountedTypeAsRawPtr : false_type {};
实施注意事项:如果第一个参数是指向RefCounted类型的原始指针,请选择true_type。否则,跳过第一个参数并递归地检查其余的参数。
template <typename T, typename... Args>
struct HasRefCountedTypeAsRawPtr<T, Args...>
: SelectType<NeedsScopedRefptrButGetsRawPtr<T>::value,
true_type,
HasRefCountedTypeAsRawPtr<Args...>>::Type {};
当|is_method|为true且|Args|的第一项为数组类型时,BindsArrayToFirstArg选择true_type。
实现注意:此非特化案例仅处理!is_method的情况和zero-arity的情况。
其他情况应由以下特化代码处理。
template <bool is_method, typename... Args>
struct BindsArrayToFirstArg : false_type {};
template <typename T, typename... Args>
struct BindsArrayToFirstArg<true, T, Args...> : is_array<T> {};
HasRefCountedParamAsRawPtr与HasRefCountedTypeAsRawPtr相同,除非|is_method|为true,HasRefCountedParamAsRawPtr跳过第一个参数。
实现注意:此非特化案例仅处理!is_method的情况和zero-arity的情况。
其他情况应由以下特化代码处理。
template <bool is_method, typename... Args>
struct HasRefCountedParamAsRawPtr : HasRefCountedTypeAsRawPtr<Args...> {};
template <typename T, typename... Args>
struct HasRefCountedParamAsRawPtr<true, T, Args...>
: HasRefCountedTypeAsRawPtr<Args...> {};
RunnableAdapter<>
RunnableAdapter<>模板为调用函数指针、方法指针或const方法指针提供了统一的接口。适配器公开具有适当签名的Run()方法。
使用这个包装器可以编写支持所有三种指针类型的代码,而不会有不必要的重复。
没有它,许多代码将需要重复3次。
对于方法的指针和const方法的指针,第一个要Run()的参数被认为是被接收到的方法。这类似于STL的mem_fun()。
此类还公开了 RunType typedef ,它是Run()函数的函数类型。
当且仅当包装器包含方法或const方法指针时,将暴露IsMethod typedef。
该类型函数(而不是值)的存在表明wrapper应该被视为method wrapper。
template <typename Functor>
class RunnableAdapter;
// Function.
template <typename R, typename... Args>
class RunnableAdapter<R(*)(Args...)> {
public:
typedef R (RunType)(Args...);
explicit RunnableAdapter(R(*function)(Args...))
: function_(function) {
}
R Run(typename CallbackParamTraits<Args>::ForwardType... args) {
return function_(CallbackForward(args)...);
}
private:
R (*function_)(Args...);
};
// Method.
template <typename R, typename T, typename... Args>
class RunnableAdapter<R(T::*)(Args...)> {
public:
typedef R (RunType)(T*, Args...);
typedef true_type IsMethod;
explicit RunnableAdapter(R(T::*method)(Args...))
: method_(method) {
}
R Run(T* object, typename CallbackParamTraits<Args>::ForwardType... args) {
return (object->*method_)(CallbackForward(args)...);
}
private:
R (T::*method_)(Args...);
};
// Const Method.
template <typename R, typename T, typename... Args>
class RunnableAdapter<R(T::*)(Args...) const> {
public:
typedef R (RunType)(const T*, Args...);
typedef true_type IsMethod;
explicit RunnableAdapter(R(T::*method)(Args...) const)
: method_(method) {
}
R Run(const T* object,
typename CallbackParamTraits<Args>::ForwardType... args) {
return (object->*method_)(CallbackForward(args)...);
}
private:
R (T::*method_)(Args...) const;
};
ForceVoidReturn<>
支持强制函数返回类型为空的一组模板。
template <typename Sig>
struct ForceVoidReturn;
template <typename R, typename... Args>
struct ForceVoidReturn<R(Args...)> {
typedef void(RunType)(Args...);
};
// FunctorTraits<>
//
// See description at top of file.
template <typename T>
struct FunctorTraits {
typedef RunnableAdapter<T> RunnableType;
typedef typename RunnableType::RunType RunType;
};
template <typename T>
struct FunctorTraits<IgnoreResultHelper<T>> {
typedef typename FunctorTraits<T>::RunnableType RunnableType;
typedef typename ForceVoidReturn<
typename RunnableType::RunType>::RunType RunType;
};
template <typename T>
struct FunctorTraits<Callback<T>> {
typedef Callback<T> RunnableType;
typedef typename Callback<T>::RunType RunType;
};
MakeRunnable<>
使用类型推断将传入的仿函数转换为RunnableType。
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;
}
InvokeHelper<>
有3个逻辑InvokeHelper<>特化:normal、void-return、WeakCalls。
普通类型只调用基础Runnable。
为了支持IgnoreResult(),我们需要一个InvokeHelper来处理void返回类型。
通常,如果Runnable的RunType返回为空,则模板系统将只接“return functor.Run()”,而忽略了将void函数与Return一起使用这一事实。
当Runnable的RunType不是空的时,这个猜想就会被打破。
因此,我们需要部分特化来更改语法,从调用中删除“return”。
WeakCalls同样需要应用于第一个参数的特殊语法,以检查它们是否应该自己执行no-op。
template <bool IsWeakCall, typename ReturnType, typename Runnable,
typename ArgsType>
struct InvokeHelper;
template <typename ReturnType, typename Runnable, typename... Args>
struct InvokeHelper<false, ReturnType, Runnable, TypeList<Args...>> {
static ReturnType MakeItSo(Runnable runnable, Args... args) {
return runnable.Run(CallbackForward(args)...);
}
};
template <typename Runnable, typename... Args>
struct InvokeHelper<false, void, Runnable, TypeList<Args...>> {
static void MakeItSo(Runnable runnable, Args... args) {
runnable.Run(CallbackForward(args)...);
}
};
template <typename Runnable, typename BoundWeakPtr, typename... Args>
struct InvokeHelper<true, void, Runnable, TypeList<BoundWeakPtr, Args...>> {
static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, Args... args) {
if (!weak_ptr.get()) {
return;
}
runnable.Run(weak_ptr.get(), CallbackForward(args)...);
}
};
#if !defined(_MSC_VER)
template <typename ReturnType, typename Runnable, typename ArgsType>
struct InvokeHelper<true, ReturnType, Runnable, ArgsType> {
WeakCall仅支持具有空返回类型的函数。
否则,如果WeakPtr<>无效,则不会定义函数结果。
COMPILE_ASSERT(is_void<ReturnType>::value,
weak_ptrs_can_only_bind_to_methods_without_return_values);
};
#endif
// Invoker<>
//
// See description at the top of the file.
template <typename BoundIndices,
typename StorageType, typename Unwrappers,
typename InvokeHelperType, typename UnboundForwardRunType>
struct Invoker;
template <size_t... bound_indices,
typename StorageType,
typename... Unwrappers,
typename InvokeHelperType,
typename R,
typename... UnboundForwardArgs>
struct Invoker<IndexSequence<bound_indices...>,
StorageType, TypeList<Unwrappers...>,
InvokeHelperType, R(UnboundForwardArgs...)> {
static R Run(BindStateBase* base,
UnboundForwardArgs... unbound_args) {
StorageType* storage = static_cast<StorageType*>(base);
本地引用,使调试器调试更容易。
如果在调试器中,你肯定想要提前完成下面的InvokeHelper<>::MakeItSo()调用。
return InvokeHelperType::MakeItSo( storage->runnable_, Unwrappers::Unwrap(get<bound_indices>(storage->bound_args_))..., CallbackForward(unbound_args)...); } };
BindState<>
这存储了传递到Bind()中的所有状态,也是大多数模板解析发生的神奇地方。
Runnable是我们要绑定参数的仿函数。
RunType是Callback<>应该使用的Run()函数的类型。
通常,这与Runnable的RunType相同,但如果使用了IgnoreResult()这样的适配器,则可能有所不同。
BoundArgsType 包含使用函数类型的所有绑定参数的存储类型。
template <typename Runnable, typename RunType, typename BoundArgList>
struct BindState;
template <typename Runnable,
typename R,
typename... Args,
typename... BoundArgs>
struct BindState<Runnable, R(Args...), TypeList<BoundArgs...>> final
: public BindStateBase {
private:
using StorageType = BindState<Runnable, R(Args...), TypeList<BoundArgs...>>;
using RunnableType = Runnable;
// true_type if Runnable is a method invocation and the first bound argument
// is a WeakPtr.
using IsWeakCall =
IsWeakMethod<HasIsMethodTag<Runnable>::value, BoundArgs...>;
using BoundIndices = MakeIndexSequence<sizeof...(BoundArgs)>;
using Unwrappers = TypeList<UnwrapTraits<BoundArgs>...>;
using UnboundForwardArgs = DropTypeListItem<
sizeof...(BoundArgs),
TypeList<typename CallbackParamTraits<Args>::ForwardType...>>;
using UnboundForwardRunType = MakeFunctionType<R, UnboundForwardArgs>;
using InvokeHelperArgs = ConcatTypeLists<
TypeList<typename UnwrapTraits<BoundArgs>::ForwardType...>,
UnboundForwardArgs>;
using InvokeHelperType =
InvokeHelper<IsWeakCall::value, R, Runnable, InvokeHelperArgs>;
using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), TypeList<Args...>>;
public:
using InvokerType = Invoker<BoundIndices, StorageType, Unwrappers,
InvokeHelperType, UnboundForwardRunType>;
using UnboundRunType = MakeFunctionType<R, UnboundArgs>;
BindState(const Runnable& runnable, const BoundArgs&... bound_args)
: BindStateBase(&Destroy),
runnable_(runnable),
ref_(bound_args...),
bound_args_(bound_args...) {}
RunnableType runnable_;
MaybeScopedRefPtr<HasIsMethodTag<Runnable>::value, BoundArgs...> ref_;
Tuple<BoundArgs...> bound_args_;
private:
~BindState() {}
static void Destroy(BindStateBase* self) {
delete static_cast<BindState*>(self);
}
};
} // namespace internal
} // namespace base