17次发布
0.7.2 | 2023年3月22日 |
---|---|
0.7.0 | 2022年2月17日 |
#427 在 异步
63 每月下载
用于 selectme-macros
56KB
654 行
selectme
异步编程的快速且公平的选择!实现。
使用方法
将以下内容添加到您的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
发布,我们可以发布另一个破坏性的版本之前。在这段时间内,您可以在这些宏中找到它们。
内联宏
它不是直接等待,而是计算Select或StaticSelect的实例,从而实现更有效的多路复用和复杂的控制流。
当与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));