#future #wrap #poll #track #modify #outcome #polling

future-wrap

一个最小的crate,允许您包装一个future来跟踪每次poll和修改结果

2个版本

0.1.1 2022年4月20日
0.1.0 2022年4月20日

#8 in #polling

MIT 许可证

6KB

rust-future-wrap

一个最小的crate,允许您包装一个future来跟踪每次poll和修改结果。

它只包含一个名为 WrapFuture 的单个trait,它为所有实现 std::future::Future 的类型添加了一个 wrap 函数。该 wrap 函数接受一个闭包作为参数,该闭包将在future被poll时被调用。闭包接收包装后的 Pin<Future> 并负责使用接收到的waker上下文调用其上的 poll。闭包可以返回任何类型 Tstd::task::Poll<T>,因此可以修改包装future的返回类型(类似于 Future.map)。

示例

此示例展示了如何跟踪和限制在poll future上花费的时间。

use std::future::Future;
use std::task::Poll;
use std::time::{Duration, Instant};

use tokio::runtime::Builder;
use tokio::time::sleep;

use future_wrap::WrapFuture;

async fn some_async_fn() {
    sleep(Duration::from_secs(1)).await;
    std::thread::sleep(Duration::from_millis(3));
    sleep(Duration::from_secs(1)).await;
    std::thread::sleep(Duration::from_millis(3));
    sleep(Duration::from_secs(1)).await;
    std::thread::sleep(Duration::from_millis(3));
    sleep(Duration::from_secs(1)).await;
    std::thread::sleep(Duration::from_millis(3));
    sleep(Duration::from_secs(1)).await;
}

fn main() {
    let runtime = Builder::new_current_thread()
        .enable_time()
        .build()
        .unwrap();

    runtime.block_on(async move {
        let fut = some_async_fn();

        let mut remaining_time = Duration::from_millis(10);
        fut.wrap(|fut, cx| {
            let poll_start = Instant::now();

            println!("Poll start");
            let res = fut.poll(cx);
            println!("Poll end");

            remaining_time = remaining_time.saturating_sub(poll_start.elapsed());
            if remaining_time.is_zero() {
                println!("Too much time spent on polls :(");
                Poll::Ready(None)
            } else {
                res.map(|v| Some(v))
            }
        }).await;
    });
}

依赖项

~0.3–0.8MB
~18K SLoC