futures-concurrency
Structured concurrency operations for async Rust
7.7.1
9.4M downloads/mo
#3212 most downloaded on crates.io
yoshuawuyts/futures-concurrency
What this package is like to depend on
Last release 7 months ago
18 Jan 2026
Release timing varies
gaps range from 2 weeks to 12 months
Some releases are documented
notes for 10 of 31 stable releases
Nothing withdrawn
no release was ever pulled
5 years old
31 releases · first in 2021
2 releases in the last 12 months
see the full history below
Release timeline
31 releases · Aug 2021 to Jan 2026Releases
latest 31-
7.7.118 Jan 2026Release notes
Open source →What's Changed
- fix(indexer): use a static divisor when possible by @Ddystopia in #217
Full Changelog: v7.7.0...v7.7.1
-
7.7.011 Jan 2026Release notes
Open source →What's Changed
- fix unused-mut error by @yoshuawuyts in #212
- Fix future docs: Replace Merge with Join by @philippgl in #211
- Add up to 15 join/try_join tuple items by @TTWNO in #208
- fix: make
futures-bufferedoptional dependency in respect toallocby @Ddystopia in #207 - Don't include default features of slab by @emil-e in #206
- fix: prepare for edition 2024 by @reneleonhardt in #209
- Fix pin violations by @matheus-consoli in #218
- use
FutureGroupfor concurrent streams by @matheus-consoli in #219 - handle empty collections by @matheus-consoli in #220
New Contributors
- @philippgl made their first contribution in #211
- @TTWNO made their first contribution in #208
- @Ddystopia made their first contribution in #207
- @emil-e made their first contribution in #206
- @reneleonhardt made their first contribution in #209
Full Changelog: v7.6.3...v7.7.0
-
7.6.329 Jan 2025Release notes
Open source →What's Changed
- fix: nightly
clippy::needless_lifetimeswarnings by @crepererum in #200 - Bump old dependencies by @matheus-consoli in #199
- Fix RaceOk tuple and array impls by @jstarks in #204
New Contributors
Full Changelog: v7.6.2...v7.6.3
- fix: nightly
-
7.6.224 Oct 2024Release notes
Open source →What's Changed
- fix:
clippy::doc_lazy_continuationby @crepererum in #192 - chore: replace
bitvecwithfixedbitsetby @crepererum in #191 - Implement
FromConcurrentStreamforResult<Vec<T>, E>by @tyilo in #193 - Reference flush instead of finnish in
ConsumerState::Breakdoc by @tyilo in #194 - fix
no_stdby @Easyoakland in #196
New Contributors
- @crepererum made their first contribution in #192
- @tyilo made their first contribution in #193
- @Easyoakland made their first contribution in #196
Full Changelog: v7.6.1...v7.6.2
- fix:
-
7.6.109 Jun 2024Release notes
Open source →What's Changed
- Add checks for msrv and semver by @matheus-consoli in #181
- Fix markdown punctuation in documentation of ConcurrentStream::take by @dtolnay in #186
- Fix pin violation in much of concurrentstream by @conradludgate in #187
- Add new benchmark for
FutureGroupby @soooch in #179
New Contributors
- @dtolnay made their first contribution in #186
- @conradludgate made their first contribution in #187
- @soooch made their first contribution in #179
Full Changelog: v7.6.0...v7.6.1
-
7.6.012 Apr 2024Release notes
Open source →✨ Portable Concurrent Async Iteration ✨
This release introduces the
ConcurrentStreamAPI: a concurrentasync/.awaitadaptation of Rayon'sParallelStreamAPI. We've been trying to implement this API for the past six or so years, and we've happy to announce we finally have a working implementation!The main feature that sets this implementation apart from other, similar attempts is that it works for any existing
Streamimpl. All you need to do is call the.co()method to obtain aConcurrentStream, and from that point allStreamcombinators should just work as expected:use futures_concurrency::prelude::*; let v: Vec<_> = stream::repeat("chashu") .co() // ← call this to convert any `Stream` into a `ConcurrentStream` .take(2) .map(|msg| async move { format!("hello {msg}") }) .collect() .await; assert_eq!(v, &["hello chashu", "hello chashu"]);
See the call to
collectat the end there? That's right: that's concurrent async iteration, collecting back into a single structure. This makes writing fan-out/fan-in pipelines trivial to author. But that's not all: in addition to converting into collections, we can also directly convert collections intoConcurrentStreamimplementations too:use futures_concurrency::prelude::*; let v: Vec<_> = vec!["chashu", "nori"] .into_co_stream() // ← call this to convert collections into concurrent async iterators .map(|msg| async move { format!("hello {msg}") }) .collect() .await;
The amount of concurrency by default is unbounded, but can be bounded by calling the limit method. This will apply backpressure should the stream produce items faster than the concurrent iterator can process them.
This API also resolves the buffered streams problem.
ConcurrentStreamremoves the need for the dreaded combination of mapping to futures and then calling the futures-rsbufferedmethod. Instead it ensures that the processing of items in a loop always happens in concert with the execution of the concurrent futures 1.Notably this API will work with any async runtime or async framework, because it makes no assumptions about the underlying runtime. The only assumption is makes is that an allocator is available. This means that at this time, unlike most other APIs in
futures-concurrencythis will not work on#[no_std]environments. This, however, is not an inherent restriction but merely an artifact of the implementation. In the future we may explore porting this to a#[no_std]compatible version - this will require some minor API changes, but should, as a system, likely work.In order to make this system work with parallel execution it should be possible to write a custom adapter. We encourage async runtimes to wrap the
ConcurrentStreamtrait exposed in this crate to create their ownParallelStreamsystem. This can depend on the runtime, and ensure that all execution not only happens concurrently, but can also be scheduled on multiple cores.We're excited for people to give this a try. We certainly hope this lowers the bar for correctly applying structured, asynchronous, concurrent streaming processing in Rust!
What's Changed
- Fix clippy warnings by @matheus-consoli in #170
- Concurrent stream by @yoshuawuyts in #164
- Update docs for docs.rs by @yoshuawuyts in #174
- Fixes redundant
todo!by @yoshuawuyts in #176 - Add
{Future,Stream}::wait_untilby @yoshuawuyts in #167 - Manually track capacity of groups by @matheus-consoli in #177
Full Changelog: v7.5.0...v7.6.0
-
There is a more elaborate version of this problem we don't have a user story for yet. Rust's futures model couples "liveness" to "backpressure". In theory we might fail to send keepalive messages if we apply backpressure for too long; this is a direct artifact of queueing theory, and would be a reason to add some form of async
Future::pending/Future::poll_pendingmethod for. This is a more subtle / niche issue than "barbara battles buffered streams". But it's worth explicitly calling out the limits of our solutions. ↩
-
7.5.011 Mar 2024Release notes
Open source →This release adds support for
no_stdandallocenvironments tofutures-concurrency. Starting this release (v7.5.0) you can pass feature flags to yourCargo.tomlto select the right feature set for your environment:[dependencies] # std futures-concurrency = "7.5.0" # alloc futures-concurrency = { version = "7.5.0", default-features = false, features = ["alloc"] } # no_std futures-concurrency = { version = "7.5.0", default-features = false }
What's Changed
- Use
Waker::clone_frominternally by @miguelraz in #161 - Implement
no_stdtests by @jmintb in #159 - Add
no_stdsupport by @alexmoon in #163
New Contributors
- @miguelraz made their first contribution in #161
- @jmintb made their first contribution in #159
- @alexmoon made their first contribution in #163
Full Changelog: v7.4.3...v7.5.0
- Use
-
7.4.322 Sep 2023Release notes
Open source →This release fixes a bug introduced in v7.3.0 related to the
try_joinfamily of operations. Please consider upgrading to this release if you're running v7.3.0 or later.What's Changed
- Fix #155 by @yoshuawuyts in #157
Full Changelog: v7.4.2...v7.4.3
-
7.4.225 Aug 2023Release notes
Open source →What's Changed
- handle empty lists for
{try,}joinby @yoshuawuyts in #154
Full Changelog: v7.4.1...v7.4.2
- handle empty lists for
-
7.4.114 Aug 2023Release notes
Open source →What's Changed
- Add lending stream examples for
Grouptypes @yoshuawuyts in #151 - Fix insertion bug for
Grouptypes @yoshuawuyts in #151
Full Changelog: v7.4.0...v7.4.1
Example
use futures_concurrency::stream::StreamGroup; use lending_stream::prelude::*; use futures_lite::stream; // Setup the stream group and populate it with one stream let mut group = StreamGroup::new(); group.insert(stream::once(4)); let mut index = 3; let mut out = 0; let mut group = group.lend_mut(); while let Some((group, num)) = group.next().await { if index != 0 { // Update the group while iterating over the group's contents group.insert(stream::once(index)); index -= 1; } out += num; } assert_eq!(out, 10);
- Add lending stream examples for
-
7.4.013 Aug 2023Nothing published for this version
-
7.3.023 Jun 2023Nothing published for this version
-
7.2.122 May 2023Nothing published for this version
-
7.2.005 Apr 2023Nothing published for this version
-
7.1.105 Apr 2023Nothing published for this version
-
7.1.008 Feb 2023Nothing published for this version
-
7.0.017 Nov 2022Nothing published for this version
-
6.0.114 Oct 2022Nothing published for this version
-
6.0.014 Oct 2022Nothing published for this version
-
5.0.110 Oct 2022Nothing published for this version
-
5.0.010 Oct 2022Nothing published for this version
-
4.0.009 Oct 2022Nothing published for this version
-
3.1.008 Oct 2022Nothing published for this version
-
3.0.214 Jun 2022Nothing published for this version
-
3.0.014 Jun 2022Nothing published for this version
-
2.0.301 Mar 2022Nothing published for this version
-
2.0.201 Mar 2022Nothing published for this version
-
2.0.127 Feb 2022Nothing published for this version
-
2.0.022 Dec 2021Nothing published for this version
-
1.1.019 Oct 2021Nothing published for this version
-
1.0.029 Aug 2021Nothing published for this version