rust, future & executor

    技术2022-07-15  59

    rust, future & executor

    一个简单的 Executor

    Future提供poll的方法。每次executor来轮询future,poll方法会返回一个 Poll<> Enum,包含两种可能:Ready 或者 Pending。

    一个简单的 Executor

    一个最简单的只能执行单一future 的 executor 代码如下所示。注意这里创建了一对 Parker和 Waker。从性能方面考虑。这样一对数据结构可以放在线程本地存储,从而避免每次都需要重新创建。当轮询的结果为pending。则调用 Parker 使得线程睡眠。而 Waker 装入Context,并传入 future的poll 方法。 当 Future的自身的任务完成后,使用 waker 唤醒 executor 线程继续执行。

    Executor sample code:

    // Use the cached parker and waker. let (parker, waker) = &*cache; let cx = &mut Context::from_waker(&waker); // Keep polling until the future is ready. loop { match future.as_mut().poll(cx) { Poll::Ready(output) => return output, Poll::Pending => parker.park(), } }

    如何唤醒则是由future本身逻辑决定的。如果async 代码块包含阻塞的io操作,这时候需要启用线程池来执行具体任务,并在适当的时候用 waker 唤醒 executor继续运行。

    一个future 示例。维持一个内部计数器。每次唤醒 Future,减一,当计数器为零,返回完成。

    struct Yields(u32); impl Future for Yields { type Output = (); fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { if self.0 == 0 { Poll::Ready(()) } else { self.0 -= 1; cx.waker().wake_by_ref(); Poll::Pending } } }

    More can be found at Stjepan’s blog: Build your own block-on

    Processed: 0.012, SQL: 9