#future #no-alloc #async-cancellation

无std cancel-safe-futures

更具有取消感知能力的替代futures适配器

6次发布

0.1.5 2023年10月28日
0.1.4 2023年10月27日
0.1.2 2023年7月28日

#99异步 分类中

Download history 1998/week @ 2024-03-14 2081/week @ 2024-03-21 2182/week @ 2024-03-28 3054/week @ 2024-04-04 1881/week @ 2024-04-11 1829/week @ 2024-04-18 2338/week @ 2024-04-25 1628/week @ 2024-05-02 2922/week @ 2024-05-09 1758/week @ 2024-05-16 1536/week @ 2024-05-23 1889/week @ 2024-05-30 1216/week @ 2024-06-06 1287/week @ 2024-06-13 2410/week @ 2024-06-20 1350/week @ 2024-06-27

6,657 每月下载量

MIT/Apache

100KB
1K SLoC

cancel-safe-futures

cancel-safe-futures on crates.io Documentation (latest release) Documentation (main) License License

更具有取消感知能力的替代futures适配器。

这个crate是什么?

这个crate解决了几个相关但不同的问题

1. 可取消安全的futures适配器

futures 库包含许多适配器,使得编写异步Rust代码更加愉快。然而,其中一些组合器使得在超时、select! 分支或类似情况下的取消难以实现。

对于更详细的解释,请参阅 SinkExt::reserve 的文档。

示例

尝试使用超时循环发送项目

use cancel_safe_futures::prelude::*;
use std::time::Duration;

let mut my_sink = /* ... */;

// This item is stored here and will be set to None once the loop exits successfully.
let mut item = Some("hello".to_owned());
let do_flush = false;

while item.is_some() {
    match tokio::time::timeout(Duration::from_secs(10), my_sink.reserve()).await {
        Ok(Ok(permit)) => {
            let item = item.take().unwrap();
            if !do_flush {
                // permit.feed() feeds the item into the sink without flushing
                // the sink afterwards. This is a synchronous method.
                permit.feed(item)?;
            } else {
                // Alternatively, permit.send() writes the item into the sink
                // synchronously, then returns a future which can be awaited to
                // flush the sink.
                permit.send(item)?.await?;
            }
        }
        Ok(Err(error)) => return Err(error),
        Err(timeout_error) => continue,
    }
}

2. 不执行取消的 then_try 适配器

futures 和 tokio 库附带了许多 try_ 适配器和宏,例如 tokio::try_join!。这些适配器具有以下特性:如果考虑的futures之一失败,所有其他futures都将被取消。

这并不总是期望的,并导致了正确性错误(例如,omicron PR 3707)。为了解决这个问题,这个crate提供了一组 then_try 适配器和宏,它们的行为类似于它们的 try_ 对应物,但如果有或多个futures出错,其他futures仍将运行到完成。

then_try 家族包括

  • join_then_try:类似于 tokio::try_join
  • future::join_all_then_try:类似于 futures::future::try_join_all
  • TryStreamExt:包含替代扩展方法到 futures::stream::TryStreamExt,例如 collect_then_try

示例

有关详细示例,请参阅 join_then_try 宏的文档。

3. 可取消安全的互斥锁

Tokio 附加的 tokio::sync::Mutex 在实际使用中导致了许多错误,尤其是在取消操作方面。

此包提供了一个替代的互斥锁 sync::Mutex,它没有这些缺陷。更多信息,请参阅 sync::Mutex 的文档。

4. 协作取消

像 Tokio 这样的执行器通过 tokio::task::JoinHandle::abort 这样的设施支持异步任务的强制取消。然而,这可能会在任何任意的等待点上引起取消。如果未来正处于取消不安全代码的中间,这可能导致不变量违反或其他问题。

相反,异步取消可以以协作方式进行:代码可以通过 tokio::select! 显式检查取消。此包提供了一个 coop_cancel 模块,可用于实现此目标。

示例

有关详细示例,请参阅 coop_cancel 的文档。

注意事项

此库尚未完成:根据需要添加适配器和宏。如果您需要尚未实现的适配器,请打开一个问题或拉取请求。

可选功能

  • macros(默认启用):启用宏。
  • std(默认启用):启用依赖于 std 的项目,包括依赖于 alloc 的项目。
  • alloc(默认启用):启用依赖于 alloc 的项目。
  • parking_lot:切换到 parking_lot 的互斥锁。

没有 std 的用户在导入此包时必须关闭默认功能。

许可协议

此项目可在 Apache 2.0 许可证或 MIT 许可证的条款下使用。

部分源自 futures-rs,并使用 Apache 2.0 和 MIT 许可证。

部分源自 tokio,并使用 MIT 许可证。

依赖关系

~0.5–7MB
~39K SLoC