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