Runtimes, Wakers, and the Reactor-Executor Pattern 208 Experimenting with our new runtime If you remember from Chapter 7, we implemented a join_all method to get our futures running concurrently. In libraries such as Tokio, you'll find a join_all function too, and the slightly more versatile Futures Unordered API that allows you to join a set of predefined futures and run them concurrently. These are convenient methods to have, but it does force you to know which futures you want to run concurrently in advance. If the futures you run using join_all want to spawn new futures that run concurrently with their “parent” future, there is no way to do that using only these methods. However, our newly created spawn functionality does exactly this. Let's put it to the test! An example using concurrency Note The exact same version of this program can be found in the ch08/c-runtime-executor folder. Let's try a new program that looks like this: fn main() { let mut executor = runtime::init(); executor. block_on(async_main()); } coro fn request(i: usize) { let path = format!("/{}/Hello World{i}", i * 1000); let txt = Http::get(&path). wait; println!("{txt}"); } coro fn async_main() { println!("Program starting"); for i in 0..5 { let future = request(i); runtime::spawn(future); } } This is pretty much the same example we used to show how join_all works in Chapter 7, only this time, we spawn them as top-level futures instead.