#异步编程 #tokio # #公平 #选择 #分支 #cargo

无需std selectme

异步Rust的快速且公平的选择!宏

17次发布

0.7.2 2023年3月22日
0.7.0 2022年2月17日

#427异步

Download history 1/week @ 2024-06-29 63/week @ 2024-07-06

63 每月下载
用于 selectme-macros

MIT/Apache

56KB
654

selectme

github crates.io docs.rs build status

异步编程的快速且公平的选择!实现。

查看select!inline!宏的文档。


使用方法

将以下内容添加到您的Cargo.toml

selectme = "0.7.1"

示例

以下是一个简单的示例,展示了两个分支被并发轮询。更多文档请参见select!

async fn do_stuff_async() {
    // work here
}

async fn more_async_work() {
    // work here
}

selectme::select! {
    _ = do_stuff_async() => {
        println!("do_stuff_async() completed first")
    }
    _ = more_async_work() => {
        println!("more_async_work() completed first")
    }
};

入口宏

这个crate提供了与Tokio通过#[selectme::main]#[selectme::test]提供的入口点属性兼容的属性,但有一个例外。它们不会检查(因为不能检查)启用了哪些Tokio功能,而是简单地假设您想构建一个多线程运行时,除非指定了flavor

那么为什么这个项目提供入口点宏呢?好吧,有一个与性能和易用性相关的问题,结果在Tokio本身中很难修复,因为需要保持向后兼容性。所以直到一个Tokio 2.x发布,我们可以发布另一个破坏性的版本之前。在这段时间内,您可以在这些宏中找到它们。


内联宏

inline!宏提供了select!宏的内联变体。

它不是直接等待,而是计算SelectStaticSelect的实例,从而实现更有效的多路复用和复杂的控制流。

当与static;选项结合使用时,它执行尽可能少的“魔法”,以复用多个异步操作,这使得它适合高效和自定义抽象。

use std::time::Duration;
use tokio::time;

async fn async_operation() -> u32 {
    // work here
}

let output = selectme::inline! {
    output = async_operation() => Some(output),
    () = time::sleep(Duration::from_secs(5)) => None,
}.await;

match output {
    Some(output) => {
        assert_eq!(output, 42);
    }
    None => {
        panic!("operation timed out!")
    }
}

更有趣的技巧是通过static;选项生成StaticSelect,它可以被适当命名并在另一个future中使用。

use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::time::Duration;

use pin_project::pin_project;
use selectme::{Random, StaticSelect};
use tokio::time::{self, Sleep};

#[pin_project]
struct MyFuture {
    #[pin]
    select: StaticSelect<u8, (Sleep, Sleep), Random, Option<u32>>,
}

impl Future for MyFuture {
    type Output = Option<u32>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let this = self.project();
        this.select.poll_next(cx)
    }
}

let s1 = time::sleep(Duration::from_millis(100));
let s2 = time::sleep(Duration::from_millis(200));

let my_future = MyFuture {
    select: selectme::inline! {
        static;

        () = s1 => Some(1),
        _ = s2 => Some(2),
        else => None,
    }
};

assert_eq!(my_future.await, Some(1));

依赖项