Macro anony::join_cyclic
source · join_cyclic!() { /* proc-macro */ }
future
only.Expand description
Returns a future that “joins” multiple futures that will be completed concurrently, using cycling polling strategy.
Usage note: If you are not sure which one to use (between this macro with join!
), just use the latter.
It’s output is a tuple of input futures’ outputs.
It is more efficient than awaiting futures like this: (fut1.await, fut2.await, fut3.await)
, since these futures will be resolved
sequencially (fut1
must be done first before awaiting fut2
, and fut3
). join!(fut1, fut2, fut3).await
will poll every futures
on getting polled, which makes them concurrently awaited.
This future will cycle the first future to be polled for each time it is polled, which is similar to the tokio’s one.
For example, join!(fut1, fut2, fut3)
polls fut1
first for the first time being polled, then it polls ‘fut2’ for the second time,
then fut3
will be the first, then it rolls back to fut1
, and so on. This strategy ensure fairness as it reduces the chance that
heavy futures may make other futures stuck.
If fairness is not your concern, consider using join!
, which is less fairer but more efficient.
§Possible differences from other implementations
-
join_cyclic!
returns an instance of an anonymous type implementedFuture
instead of requiring it to be inside anasync
. You will be warned if you neither.await
,poll
, nor return it. -
input futures are required to implement
IntoFuture
. -
the returned future (generally) has smaller size and is (generally) faster.
-
the returned future is
Unpin
if all of the input futures areUnpin
.
§Examples
use anony::join_cyclic;
let a = async { 1 };
let b = async { 2 };
let c = async { 3 };
assert_eq!(join_cyclic!(a, b, c).await, (1, 2, 3));
If you want to run a future (or more) while doing something else, this macro is a help! Note that you must put the “something else” after every other futures you want to run:
use anony::join_cyclic;
use tokio::time::sleep;
use std::time::Duration;
async fn read_db() -> String {
sleep(Duration::from_secs(1)).await;
"My secret".into()
}
let (secret_value, _) = join_cyclic!(read_db(), async {
// Your other tasks go here, maybe asynchronous or just blocking...
let a = 1;
let b = 2;
assert_eq!(a + b, 3);
}).await;
assert_eq!(secret_value, "My secret");