#future #async-executor #async #no-std

nightly no-std worst-executor

异步的最简单执行器。

2个版本

0.1.1 2023年1月26日
0.1.0 2023年1月26日

#1105 in 异步

MIT/Apache

18KB
195

最坏执行器

Build status Latest version License dependency status

可能的最简单异步执行器。
这个crate提供了一个名为 block_on 的单一函数,它接受一个future并在future解决之前阻塞当前线程。
它的工作方式是通过“自旋循环”遍历 poll 方法,直到它准备好。

好事是它可以非常有效地优化,例如 worst_executor::block_on(async { 42 }) 编译为单个 mov 指令。

不好的一面是它实际上并不进行任何调度,这意味着如果你等待一个永远不会解决的future,你的程序将会挂起。这也是你可能不希望使用它的原因。

请注意,由于其简单性,该库仅使用 core,不需要 stdalloc,也没有任何依赖,实际上只有16行代码。

用法

将此添加到你的 Cargo.toml

[dependencies]
worst-executor = "0.1"

然后在你的 main.rs 中


fn main() {
    worst_executor::block_on(async {
        // Your async code goes here.
    });
}

用例

比如说,你正在使用一个返回future的库,但你知道它不进行I/O,你希望在不引入完整的异步运行时(如tokio/smol/async-std)的情况下,在同步上下文中使用它。
你可以使用 worst_executor::block_on 来阻塞当前线程,直到future解决。

另一个场景可能是你希望在单个线程中运行“事件循环”,使用 async rust。因此,你可以使用 core::future::join 宏与 futures::select 宏一起处理程序的控制流,同时在单个线程上运行且永不释放。

单线程tcp服务器

use async_net::{TcpListener, TcpStream};
use futures::{stream::FuturesUnordered, AsyncReadExt, AsyncWriteExt, StreamExt};
use worst_executor::block_on;

block_on(async {
    let listener = TcpListener::bind("127.0.0.1:8080").await.unwrap();
    let mut connection_handlers = FuturesUnordered::new();
    // This stream is infinite so it's OK to call fuse.
    let mut listener = listener.incoming().fuse();
    loop {
        futures::select! {
            new_connection = listener.select_next_some() => connection_handlers.push(handle_connection(new_connection?)),
            socket = connection_handlers.select_next_some() =>
                if let Some(socket) = socket {
                    connection_handlers.push(handle_connection(socket));
                },
        }
    }
})

async fn handle_connection(mut stream: TcpStream) -> Option<TcpStream> {
    let mut buf = [0u8; 1024];
    let n = match stream.read(&mut buf).await {
        Ok(n) if n == 0 => return Some(stream),
        Ok(n) => n,
        Err(e) => {
            eprintln!("failed to read from the socket {e:?}");
            return None;
        }
    };
    // Write the data back
    stream.write_all(&buf[0..n]).await
            .map_err(|e| eprintln!("failed to write to the socket {e:?}"))
            .map(|()| stream)
            .ok()
}

无运行时依赖