join_me_maybe!

join_me_maybe! is an expanded version of the futures::join!/tokio::join! macro, with
some added features for cancellation and early exit. Programs that need this sort of thing
often resort to "select! in a loop", but that comes with a notoriously long list of
footguns.[1][2][3] The goal of join_me_maybe!
is to be more convenient and less error-prone than select!-in-a-loop for its most common
applications. The stretch goal is to make the case that select!-in-a-loop should be
considered harmful, as they say.
Examples
The basic use case works like join!, polling each of its arguments to completion and
returning their outputs in a tuple.
use join_me_maybe;
use ;
// Create a couple futures, one that's ready immediately, and another that takes some time.
let future1 = ready;
let future2 = async ;
// Run them concurrently and wait for both of them to finish.
let = join_me_maybe!;
assert_eq!;
(This is an example to get us started, but in practice I would just use join! here.)
maybe cancellation
If you don't want to wait for all of your futures finish, you can use the maybe keyword. This
can be useful with infinite loops of background work that never actually exit. The outputs of
maybe futures are wrapped in Option.
let outputs = join_me_maybe!;
assert_eq!;
label: and .cancel()
You can also cancel futures by name if you label: them. The outputs of labeled futures are
wrapped in Option too.
let mutex = new;
let outputs = join_me_maybe!;
assert_eq!;
A .cancel()ed future won't be polled again, and it'll be dropped promptly, freeing any locks
or other resources that it might be holding. Note that if a future cancels itself, its
execution still continues as normal after .cancel() returns, up until the next .await
point. This can be useful in closure bodies or nested async blocks, where return or break
doesn't work.
no_std
join_me_maybe! is compatible with #![no_std]. It has no runtime dependencies and does not
allocate.