Skip to content
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

Figure out a way to race multiple futures in smol #292

Closed
notgull opened this issue Dec 21, 2023 · 5 comments
Closed

Figure out a way to race multiple futures in smol #292

notgull opened this issue Dec 21, 2023 · 5 comments

Comments

@notgull
Copy link
Member

notgull commented Dec 21, 2023

Generally in smol we frown on large combinators and prefer using the executor when possible. For instance, instead of joining a bunch of different futures, we spawn the futures on an Executor and then wait on each of the Task handles.

However this isn't a good solution to or or race. Ideally we would have a way to spawn a bunch of futures on an Executor and then have a way to wait on one of those tasks.

cc @i509VCB, @smol-rs/admins Would appreciate brainstorming on a good solution to this problem, as one isn't immediately apparent to me.

@notgull
Copy link
Member Author

notgull commented Dec 21, 2023

One way of doing this would be with a channel.

let (sender, receiver) = async_channel::bounded(1);
let ex = Executor::new();

let mut handles = vec![];

// Spawn all of the futures.
for future in futures_to_race {
    handles.push(ex.spawn({
        let sender = send.clone();
        async move {
            // Send the result of the future down the channel.
            sender.send(future.await).await.ok();
        }
    });
}

// Run the executor while waiting for the result.
let result = ex.run(receiver.recv()).await.unwrap();
for handle in handles {
    handle.cancel().await;
}

However, this is pretty unwieldy and I would like a way to implement this pattern in a simpler way. Same could probably go for the zip and or patterns.

@fogti
Copy link
Member

fogti commented Dec 21, 2023

A fully generic channel looks a like a bit too much, why not e.g. a once_cell, an event and a flag (or just some kind of one-shot channel with clonable sending end)?

@notgull
Copy link
Member Author

notgull commented Dec 22, 2023

Although that would work, it's unfair to expect this burden to fall onto the user. My idea was to create an async-executor-util (name open to suggestions) crate to have all of the combinators that would be needed for this.

@fogti
Copy link
Member

fogti commented Dec 24, 2023

ok, oh some additional prior art would also be https://github.com/YZITE/server-executor, which I wrote to have an executor for tests, simple async servers, etc.

@notgull
Copy link
Member Author

notgull commented Mar 13, 2024

I think the futures-concurrency crate provides a good solution to this problem for now, at least on the short scale. For larger scale futures we'll wait for a conclusion in smol-rs/futures-lite#93.

@notgull notgull closed this as completed Mar 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants