use std::time::Duration; use tokio::fs; use tokio::time; async fn print_100() -> usize { // return type is to demonstrate syntax sugar that is available through "async" prefix // actual return type is more complicated. let mut count = 0; while count < 10 { println!("---------------SPAWNED FUTURE OUTPUT: {count}!!!!!--------"); time::sleep(Duration::from_nanos(1)).await; count += 1; } count } #[tokio::main] // this macro expands into code that creates a runtime for executing futures // when awaited, the future is sent to the runtime created by it. // I'm using a multi-threaded runtime(tokio feature flag "rt-multi-thread"), which creates schedules // = number of CPUs available by default async fn main() { // working directory that is supplied by cargo is crate/program root let future = fs::read_to_string("./src/async-tokio.rs"); // spawning a future is the same as backgrounding it let spawn_handle = tokio::spawn(print_100()); let contents = future.await.unwrap(); // Rust futures are lazily evaluated, they have to be "awaited" for execution. // When awaited, this line of execution is blocked until the future runs to completion // rustc will complain about dead code if the following line is commented out: println!("{contents}"); spawn_handle.await.unwrap(); // waiting for the spawned future to run to completion }