dangarbri
dangarbri

Reputation: 551

How can I wait for a specific result from a pool of futures with async rust?

Using the futures crate.

I have a vec of futures which return a bool and I want to wait specifically for the future that returns true.

consider the following pool of futures.

async fn async_function(guess: u8) -> bool {
    let random_wait = rand::thread_rng().gen_range(0..2);
    std::thread::sleep(std::time::Duration::from_secs(random_wait));
    println!("Running guess {guess}");
    guess == 231
}

fn main() {
    let mut pool: Vec<impl Future<Output = bool>> = vec![];
    for guess in 0..=255 {
        pool.push(async_function(guess));
    }
}

I'm new to async rust, so I've been looking at the async-book.

From there, these are the options I've considered:

Upvotes: 3

Views: 563

Answers (1)

dangarbri
dangarbri

Reputation: 551

Ok, my thinking of futures was wrong. I knew that they weren't executed immediately, but I wasn't using the executors correctly from the futures crate.

Here's what I've got that seems to work.

let thread_pool = ThreadPool::new().unwrap();
let mut pool = vec![];
for guess in 0..=255 {
    let thread = thread_pool.spawn_with_handle(async_fn(guess)).expect("Failed to spawn thread");
    pool.push(thread.into_stream());
}

let stream = block_on_stream(futures::stream::select_all(pool));
for value in stream {
    println!("Got value {value}");
}

the thread pool executor is what creates the separate threads needed to run. Without this my application was single threaded so no matter what I tried, it would only run functions one at a time, not concurrently.

This way I spawn each request into the thread pool. The thread pool appears to spawn 4 background threads. By pushing them all into a stream, using select_all, and iterating over the stream, my main thread blocks until a new value is available.

There's always 4 workers and the thread pool is scheduling them in the order they were requested like a queue. This is perfect.

Upvotes: 1

Related Questions