-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a new future::FutureGroup
type for dynamic async concurrency
#147
Conversation
Actually, now that I think of it: we probably should remove the |
Okay, done - removed the handle! There is still a real question about how to weave through the handle pattern though. I briefly tried this test case, but it doesn't work out because of the lifetimes: #[test]
fn concurrent_channel() {
enum Message<T> {
Future(Pin<Box<dyn Future<Output = T> + 'static>>),
Output(T),
}
futures_lite::future::block_on(async {
let mut set = FutureSet::new();
let (sender, receiver) = async_channel::bounded(1);
sender.try_send(async { 2 + 2 }).unwrap();
let receiver = receiver.map(|t| Message::Future(Box::pin(t)));
set.insert(async { Message::Output(1 + 1) });
let mut stream = (set, receiver).merge();
let mut out = 0;
while let Some(msg) = stream.next().await {
match msg {
Message::Future(fut) => set.insert(async move { // `set` has been moved
let output = fut.await;
Message::Output(output)
}),
Message::Output(num) => out += num,
}
}
assert_eq!(out, 6);
});
} I'm pretty certain there is some formulation of let mut iter = vec![0; 1]).into_async_iter().lend_mut();
let mut appended = false;
while let Some((item, vec)) = iter.next().await {
if !appended {
vec.push(item + 1);
appended = true;
}
println!("{item}");
} We should explore some options with this:
|
@yoshuawuyts, am I missing something, or does adding a - impl<I: AsyncIterator > AsyncLendingIterator for LendMut<I>
+ impl<I: AsyncIterator + 'static> AsyncLendingIterator for LendMut<I>
- impl<I: AsyncIterator > AsyncLendingIterator for Lend<I>
+ impl<I: AsyncIterator + 'static> AsyncLendingIterator for Lend<I> |
@matheus-consoli we explicitly want the lifetime to be non-static. I filed rust-lang/rust#113796 which has just been fixed, so this should work again on the next nightly. |
Okay, updated it! - This now seems to work as expected, and I'm pretty happy with it. Oh CI is probably failing because this requires nightly features. If we want to move forward with this PR we should apply the proper cfgs for this to work. ExamplesHere are two examples of this in action: //! A basic example showing how to add items to the set
let mut set = FutureSet::new();
set.insert(async { 1 + 1 });
set.insert(async { 2 + 2 });
let mut out = 0;
while let Some((num, _set)) = set.next().await {
out += num;
}
assert_eq!(out, 6);
assert_eq!(set.len(), 0);
assert!(set.is_empty()); //! A more complex example, showing how to concurrently await both a channel of futures, as well as the futures received on that channel.
let mut set = FutureSet::new();
let (sender, receiver) = async_channel::bounded(1);
sender.try_send(async { 2 + 2 }).unwrap();
set.insert(async { Message::Output(1 + 1) });
set.insert(async move {
let fut = receiver.recv().await.unwrap();
Message::Future(Box::pin(fut))
});
let mut out = 0;
while let Some((msg, set)) = set.next().await {
match msg {
Message::Future(fut) => set.insert(async move {
let output = fut.await;
Message::Output(output)
}),
Message::Output(num) => out += num,
}
}
assert_eq!(out, 6); Further ImprovementsIt seems though that directly implementing let mut set = FutureSet::new();
set.insert(async { 1 + 1 });
set.insert(async { 2 + 2 });
let mut out = 0;
while let Some(num) = set.next().await {
out += num;
} Thoughts on
|
|
Updated the implementation to take homogenous future types only. This saves intermediate allocations, and allows users to choose their own strategy for unifying types. It's not without tradeoffs, but those tradeoffs seem inherent to Rust's handling of heterogenous types, and are shared by e.g. unifying the output types of |
future::FutureSet
type for dynamic async concurrencyfuture::FutureGroup
type for dynamic async concurrency
We should reimplement this on top of #149. Either by copying the impl (which should be simple enough), or by using it internally and wrapping types in |
Closing in favor of #150 |
This is similar to
FuturesUnordered
from the futures library, orJoinSet
from tokio.Example
Tasks
WakerSet
to improve performance