liveBook · Manning

Join!

As explained in Learn Rust in a Month of Lunches

join! is an asynchronous macro that concurrently drives multiple futures and completes when all of them complete.

join! is an asynchronous macro that polls multiple futures at the same time and finishes when every future completes. Unlike consecutive .await calls, it lets independent async work make progress together. section 19.3.4

Three delayed values

Call wait_and_give_u8(1), wait_and_give_u8(2), and wait_and_give_u8(3) inside join!. Each function waits for a random duration before printing. The printed order can vary, but the resulting tuple remains (1, 2, 3), preserving argument order. section 19.3.4

use rand::*;
use tokio::join;
use std::time::Duration;
 
async fn wait_and_give_u8(num: u8) -> u8 {
    let mut rng = rand::thread_rng();
    let wait_time = rng.gen_range(1..100);
    tokio::time::sleep(Duration::from_millis(wait_time)).await;
    println!("Got a number! {num}");
    num
}
 
#[tokio::main]
async fn main() {
 
    let nums = join!(
        wait_and_give_u8(1),
        wait_and_give_u8(2),
        wait_and_give_u8(3)
    );
 
    println!("{nums:?}");
}

A runnable Tokio example shows the join! invocation and its tuple result. section 19.3.4

Choose related async controls by the completion behavior you need:

  • Use join! when all futures must finish; use select! when the first completed future should determine the result. section 19.3.4
  • Use try_join! when joined futures return Results and an error should produce a failed join. section 19.3.4

How Learn Rust in a Month of Lunches covers it

How deep it goes
Defines concurrent polling through a runnable example, but stops short of explaining the macro's implementation internals.
Examples
Demonstrates three randomly delayed numeric futures whose print order varies while their tuple result stays ordered.
What it assumes
Assumes basic async functions and .await, while introducing concurrent polling through a small example.
What you can do after
Apply concurrent future polling with Tokio's join! macro and recognize its ordered tuple result.
How it connects
Connects async Rust, futures, await, Tokio, select!, and try_join! through contrasting completion and error behaviors.

Also explained in

Compare how 2 books explain join! →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Rust in a Month of Lunches. The section links point to the parts of the book it draws on.