< 返回我的博客

爱国的张浩予 发表于 2021-08-03 08:01

Tags:rust,async,future,inert

Rust异步编程浅悟(一)

不同于javascriptnew Promise((resolve, reject) => {...})构造即运行,Rust中的Future是·惰性·状态机。这体现为:

  1. 【调用异步函数】或【执行异步块】仅只构造一个Future trait object
  2. 因为Future是惰性状态机,所以它不会自动执行【异步函数】或【异步块】内的任何一行代码 --- 此点与javascript的·活性·状态机完全不同。相反,需要人工激活触发。
  3. 人工启动Future运行,又分为两个场景的两种情况:
    1. 已经在async fn内,Future.await激活。但,同时阻塞当前异步程序执行流。

    2. async fn外,需要借助由【运行时】提供的【执行器】。就async-std库而言,有两个选择:

      1. task::block_on(Future) 执行Future且阻塞当前线程直到Future被完成。
      2. task::spawn(Future)仅执行Future和不阻塞当前线程。

      无论选择上面哪种方式,若在Future执行期间出现了panic,其都会终止(abort)正在共享同一个执行线程(thread)的所有task(·无栈·协程)的运行。

题外话,

  1. 绿色线程是·有栈·协程;异步函数与异步块是·无栈·协程。
  2. async-std库的词汇表内,协程被称作task而不是惯例的coroutine
  3. task::spawn(Future)也能被使用于async fnasync {...}内。它被用来代替.await指令,以非阻塞async fnasync {...}的方式,激活与执行一个Future实例。

例程

async fn accept_loop(addr: impl ToSocketAddrs) -> Result<()> {
    // 1. TcpListener::bind(addr) 返回 Future
    // 2. .await 于 Future 取得 Result<T, E>
    // 3. Result<T, E>? 再拿得 Ok<T> 中的 T
    let listener = TcpListener::bind(addr).await?; // 异步函数内的人工启动 Future
    let mut incoming = listener.incoming();
    // 因为没有从语言层面支持 async for loop,所以 while loop + Iterator<Item = T> 来模拟之。
    while let Some(stream) = incoming.next().await {
        // TODO
    }
    Ok(())
}
fn main() {
    let fut = accept_loop("127.0.0.1:8080");
    task::block_on(fut); // 异步函数外的人工启动 Future
}

评论区

写评论

还没有评论

1 共 0 条评论, 1 页