Rust 異步狀態機

這篇文章通過一個簡單的例子,介紹一下 Rust 編譯器爲 async/await 生成的狀態機。

Future 狀態機的簡單概述如下圖:

在下面的代碼示例中,我們創建了一個頂層的 future:fut_top,它依賴於 FakeFuture 對象:fake。我們只是簡單地使用 poll 方法來驅動 fut_top 直到完成。另外,需要在 Cargo.toml 文件中引入依賴庫:

[dependencies]
futures = "0.3.1"
use futures::{
    task::{waker_ref, ArcWake}, // to create `context` from type implements ArcWake trait
    FutureExt,                  // to use `Future::boxed` method
};
use std::{
    future::Future,
    sync::Arc,
    task::{Context, Poll},
};
async fn fut_top() {
    println!("poll top future");
    let fake = FakeFuture;
    fake.await;
}
struct FakeFuture;
impl Future for FakeFuture {
    type Output = ();
    fn poll(self: std::pin::Pin<&mut Self>, _: &mut std::task::Context<'_>) -> std::task::Poll<Self::Output> {
        static mut SWITCH: bool = false;
        println!("poll fake future");
        unsafe {
            if !SWITCH {
                SWITCH = true;
                return Poll::Pending;
            }
        }
        Poll::Ready(())
    }
}
fn run(f: impl Future<Output = ()> + Send + 'static) {
    struct DummyTask;
    impl ArcWake for DummyTask {
        fn wake_by_ref(_arc_self: &Arc<Self>) {
            todo!()
        }
    }
    let task = Arc::new(DummyTask);
    let waker = waker_ref(&task);
    let context = &mut Context::from_waker(&*waker);
    let mut f = f.boxed();
    while f.as_mut().poll(context).is_pending() {
        println!("pending...");
    }
}
fn main() {
    let f = fut_top();
    println!("start to drive future!");
    run(f);
    println!("future completed!");
}

fut_top() 函數簽名前加入 async,編譯器會自動實現的 future trait,生成狀態機。當且僅當 fut_top 所依賴的 future 完成時,狀態纔是 "Poll::Ready"。從執行者的角度看 "fut_top" 是一個任務,任務是已經提交給執行者執行的頂層 future。

"fut_top" 生成的狀態機將依賴於 "fake" 的未來狀態,當我們 poll “fut_top” 時,它會 poll “fake” 的 future。

在 unsafe 語法塊中,我們只演示返回的狀態是如何影響狀態機的,實際上,它是由 “context” 管理的,例如 x.waker().wake_by_ref()。

爲了完成 future,我們只需要調用 “poll”。但是,爲了滿足 "poll" 接口,我們需要創建一個 "context" 對象。在這裏我們需要模擬一個 context 對象,所以需要創建一個 Dummy Task 類型,並從它創建一個 context 對象。

運行 cargo run 輸出:

start to drive future!
poll top future
poll fake future
pending...
poll fake future
future completed!

本文翻譯自:

https://medium.com/@gftea/async-state-machine-in-rust-e8d46af52532

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/aIpcBw6Anz4V5fLc1sOhlA