Tokio select: what is even the point of spawning? in this case

all these run at once

use tokio::time::{sleep, Duration};

const DURATION_SECS: u64 = 30;

#[tokio::main]
async fn main() {
    let inner_counter = tokio::spawn(async {
        let mut num: u128 = 0;
        for _ in 0..u128::MAX {
            num += 1;
            println!("inner {num}");
            sleep(Duration::from_secs(1)).await;
        }
    });

    let outer_counter = tokio::spawn(async {
        inner_counter.await.unwrap();
        let mut num: u128 = 0;
        for _ in 0..u128::MAX {
            num += 1;
            println!("outer {num}");
            sleep(Duration::from_secs(1)).await;
        }
    });

    let counter = async {
        let mut num: u128 = 0;
        for _ in 0..u128::MAX {
            num += 1;
            println!("counter {num}");
            sleep(Duration::from_secs(1)).await;
        }
    };

    let counter_2 = async {
        let mut num: u128 = 0;
        for _ in 0..u128::MAX {
            num += 1;
            println!("counter_2 {num}");
            sleep(Duration::from_secs(1)).await;
        }
    };

    tokio::select! {
        _ = sleep(Duration::from_secs(DURATION_SECS)) => {
            println!("{DURATION_SECS} seconds have passed.");
        },
        _ = outer_counter => {
            println!("outer_counter has completed.");
        },
        _ = counter => {
            println!("counter has completed.");
        },
        _ = counter_2 => {
            println!("counter0 has completed.");
        },
    }
}

spawn

The provided future will start running in the background immediately when spawn is called, even if you don’t await the returned JoinHandle.

Is that the info you were missing?

If you don't want them to run immediately, don't spawn them and do the select on the futures (the async expressions).

The point of spawning is to start a new (concurrent) task unconditionally. The current task continues executing.

1 Like

yeah i understand that, the prints are just ai garbage because i didnt wanna write it all out, but my point is, whats even the difference between a future and a spawn? are spawns just easier to do on a mass scale? what if i just do

thing = async {
do something costly
}

for 0..10
{
thing
}

// join them or something

that wont work, they must be handles

You await a future and the current task waits for it to run and finish. The current task does not continue until the future is finished.

A spawned task starts immediately and you don't have to await it. The current task continues executing concurrently with the spawned task. You await the spawned task (its handle) only if you need to do something when it finishes.

The main difference is whether the thing you're starting (the future or spawned task) and the current task are running concurrently or not.

They don't have to be handles, they can also be async functions, closures and blocks.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.