为什么 Rust 异步迫使实现者对“Waker”使用动态调度

fak*_*ake 2 traits dynamic-dispatch rust async-await

我正在阅读有关如何在 Rust 中实现async/await 的内容,我注意到它RawWaker本质上是一个胖指针。我不太明白为什么Waker本质上是这样实现的struct Waker{data: *const (), vtable: *const WakerVTable},而不是让编译器在编译时知道、和的Waker<T: Wakes>{raw_walker: &mut T}实现。wake()wake_ref()drop()clone()

Ian*_* S. 5

唤醒者需要具有令人难以置信的多才多艺。该博客解释了很多有关设计选择的内容,值得一读。相关部分是这样说的:

poll 阶段引入的唯一要求是动态性:因为它需要通过任意 future 传递,所以唤醒器类型不能是通用的。这意味着其他两个阶段引入的每个需求都需要动态调度

现在,作者在这里不清楚的部分是“任意期货”包括盒装期货(以及一般可以使用动态调度进行轮询的期货)。如果未来特质的定义如下:

pub trait Future {
    type Output;

    fn poll<W: Wake>(
        self: Pin<&mut Self>,
        cx: &mut Context<'_, W>,
    ) -> Poll<Self::Output>;
}
Run Code Online (Sandbox Code Playgroud)

那么该特征Future就不是对象安全的,从而消除了动态调度的可能性,这是一个破坏性的因素。