How can I make it run concurrently?
You can either:
- spawn a task, which will make every
hello_wait
be scheduled independently
- or "merge" the futures, which will concurrently drive all the futures in parallel
Your expectation might come from Javascript or C# async, where the "base" awaitable is a task. Tasks are "active", as soon as you create them they can be scheduled and do their thing concurrently.
But rust's core awaitable is more of a coroutine, so it's inert (/ passive): creating one doesn't really do anything, futures have to be polled to progress and await
will repeatedly poll until completion before resuming. So when you await
something, it runs completely with no opportunity to interleave at that point.
Therefore running futures concurrently requires one of two things:
- upgrading them to a task, meaning they can be scheduled on their own, that is what
spawn
does
- or composing futures into a single "meta-future" which can poll them all in turn when it's polled, that's what constructs like
join_all
or tokio::join
do
Note that composing futures doesn't allow parallelism, since the futures are "siblings" they can only get polled (and thus actually do things) consecutively, it's just that this polling (and thus progress) gets interleaved.
Spawning tasks does allow for parallelism (if the runtime is multithtreaded and the machine has mutiple cores -- though the latter is pretty much universal these days), but has its own limitations with respect to lifetime and memory management, and is a bit more expensive.
Here is a playground demo of various options. It uses tokio because apparently the playground doesn't have async_std, and I'm not sure it'd be possible to enable the "unstable" feature anyway, but aside from that and the use of tokio::join
(async_std's Future::join
can only join 2 futures at a time so you have to chain the call) it should work roughly the same in async_std.