2个版本
0.1.1 | 2020年8月10日 |
---|---|
0.1.0 | 2020年8月10日 |
#1014 在 过程宏
31KB
407 行
polling-async-trait
polling-async-trait
是一个库,它为你的特性创建与轮询方法相关联的异步方法。它与 async-trait
类似,但 async-trait
在 async
方法上工作,而 polling-async-trait
在 poll_
方法上工作。
用法
该库的入口点是 async_poll_trait
属性。当应用于特性时,它会扫描特性中每个带有 async_method
标记的方法。它将这些方法视为异步轮询方法,并为每个方法在特性中添加一个等效的异步方法。
use polling_async_trait::async_poll_trait;
use std::io;
#[async_poll_trait]
trait ExampleTrait {
// This will create an async method called `basic` on this trait
#[async_method]
fn poll_basic(&mut self, cx: &mut Context<'_>) -> Poll<i32>;
// polling methods can also accept &self or Pin<&mut Self>
#[async_method]
fn poll_ref_method(&self, cx: &mut Context<'_>) -> Poll<i32>;
#[async_method]
fn poll_pin_method(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<i32>;
// If `owned` is given, the generated async method will take `self` by move.
// This means that the returned future will take ownership of this instance.
// Owning futures can still be used with any of `&self`, `&mut self`, or
// `Pin<&mut Self>`
#[async_method(owned)]
fn poll_close(&mut self, cx: &mut Context<'_>) -> Poll<io::Result<()>>;
#[async_method(owned)]
fn poll_close_ref(&self, cx: &mut Context<'_>) -> Poll<io::Result<()>>;
#[async_method(owned)]
fn poll_close_pinned(self: Pin<&mut Self>, cx: &mut Context<'_>)
-> Poll<io::Result<()>>;
// you can use method_name and future_name to control the names of the
// generated async method and associated future. This will generate an
// async method called do_work, and an associated `Future` called `DoWork`
#[async_method(method_name = "do_work", future_name = "DoWork")]
fn poll_work(&mut self, cx: &mut Context<'_>) -> Poll<()>;
}
#[derive(Default)]
struct ExampleStruct {
closed: bool,
}
impl ExampleTrait for ExampleStruct {
fn poll_basic(&mut self, cx: &mut Context<'_>) -> Poll<i32> {
Poll::Ready(10)
}
fn poll_ref_method(&self, cx: &mut Context<'_>) -> Poll<i32> {
Poll::Ready(20)
}
fn poll_pin_method(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<i32> {
Poll::Ready(30)
}
fn poll_close(&mut self, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
if !self.closed {
println!("closing...");
self.closed = true;
cx.waker().wake_by_ref();
Poll::Pending
} else {
println!("closed!");
Poll::Ready(Ok(()))
}
}
fn poll_close_ref(&self, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
if !self.closed {
println!("Error, couldn't close...");
Poll::Ready(Err(io::ErrorKind::Other.into()))
} else {
println!("closed!");
Poll::Ready(Ok(()))
}
}
fn poll_close_pinned(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
let this = self.get_mut();
if !this.closed {
println!("closing...");
this.closed = true;
cx.waker().wake_by_ref();
Poll::Pending
} else {
println!("closed!");
Poll::Ready(Ok(()))
}
}
fn poll_work(&mut self, cx: &mut Context<'_>) -> Poll<()> {
Poll::Ready(())
}
}
#[tokio::main]
async fn main() -> io::Result<()> {
let mut data1 = ExampleStruct::default();
assert_eq!(data1.basic().await, 10);
assert_eq!(data1.ref_method().await, 20);
data1.do_work().await;
data1.close().await?;
let data2 = ExampleStruct::default();
assert!(data2.close_ref().await.is_err());
let mut data3 = Box::pin(ExampleStruct::default());
assert_eq!(data3.as_mut().pin_method().await, 30);
let data4 = ExampleStruct::default();
// Soundness: we can can await this method directly because it takes
// ownership of `data4`.
data4.close_pinned().await?;
Ok(())
}
生成的future类型将与特性共享可见性(即,如果特性是 pub
,它们将是 pub
,如果特性是 pub(crate)
,它们将是 pub(crate)
,等等)。
与 async-trait
的权衡
仔细考虑哪个库最适合你的用例;轮询方法通常很难编写(因为它们需要手动状态管理和处理 Pin
)。如果你的控制流很复杂,使用 async fn
和 async-trait
可能更合适。 polling-async-trait
的优点是它创建的异步方法没有开销,因为返回的futures直接调用poll方法。这意味着不需要使用类型擦除的 Box<dyn Future ... >
。
许可证:MPL-2.0
依赖关系
~1.5MB
~39K SLoC