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
Wednesday, March 6, 2019 by blast