Alternative futures adapters that are more cancellation-aware.
This crate solves two related but distinct problems:
The futures
library contains many adapters that
make writing asynchronous Rust code more pleasant. However, some of those combinators make it
hard to write code that can withstand cancellation in the case of timeouts, select!
branches
or similar.
For a more detailed explanation, see the documentation for SinkExt::reserve
.
Attempt to send an item in a loop with a timeout:
```rust use cancelsafefutures::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".toowned()); let doflush = false;
while item.issome() { match tokio::time::timeout(Duration::fromsecs(10), mysink.reserve()).await { Ok(Ok(permit)) => { let item = item.take().unwrap(); if !doflush { // 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, } }
```
then_try
adapters that don't perform cancellationsThe futures and tokio libraries come with a number of try_
adapters and macros, for example
tokio::try_join!
. These adapters have the property that if one of the futures under
consideration fails, all other futures are cancelled.
This is not always desirable and has led to correctness bugs (e.g. omicron PR
3707). To address this issue, this crate
provides a set of then_try
adapters and macros that behave like their try_
counterparts,
except that if one or more of the futures errors out, the others will still be run to
completion.
The then_try
family includes:
join_then_try
: similar to tokio::try_join
.future::join_all_then_try
: similar to futures::future::try_join_all
.TryStreamExt
: contains alternative extension methods to futures::stream::TryStreamExt
,
such as collect_then_try
.For a detailed example, see the documentation for the join_then_try
macro.
This library is not complete: adapters and macros are added on an as-needed basis. If you need an adapter that is not yet implemented, please open an issue or a pull request.
macros
(enabled by default): Enables macros.std
(enabled by default): Enables items that depend on std
, including items that depend on
alloc
.alloc
(enabled by default): Enables items that depend on alloc
.No-std users must turn off default features while importing this crate.
This project is available under the terms of either the Apache 2.0 license or the MIT license.
Portions derived from futures-rs, and used under the Apache 2.0 and MIT licenses.
Portions derived from tokio, and used under the MIT license.