macro_rules! select {
($($token:tt)*) => { ... };
(default => $body:expr) => { ... };
(complete => $body:expr) => { ... };
($pattern:pat = $future:expr $(, if $condition:expr)? => $body:expr) => { ... };
}
Expand description
§Select multiplex asynchronous futures simultaneously
select!
supports three different clauses:
- pattern = future [, if condition] => code,
- default => code,
- complete => code,
§Evaluation order
- All conditions and futures are evaluated before selection.
- Future expression is not evaluated if corresponding condition evaluated to false.
- Whenever a branch is ready, its clause is executed. And the whole select returns.
- Fail to match a refutable pattern will disable that branch.
default
clause is executed if no futures are ready. That is non blocking mode.- If all branches are disabled by conditions or refutable pattern match, it resort to
complete
ordefault
in case of nocomplete
.
§Panics
- Panic when all futures are disabled or completed and there is no
default
orcomplete
.
§Limitations
- Support up to 64 branches.
- Refutability check may cause false negative compilation error. As results are matched against
&mut output
but not value which will be fed to matching clause.
§Comparing with tokio::select!
- Future expression is only evaluated if condition meets.
This will panic in
use std::future::ready; use async_select::select; async fn guard_future_by_condition() { let opt: Option<i32> = None; let r = select! { v = ready(opt.unwrap()), if opt.is_some() => v, v = ready(6) => v, }; assert_eq!(r, 6); }
tokio::select!
as it evaluatesready(opt.unwrap())
irrespective of corresponding condition. - There is no
default
counterpart intokio::select!
. But it could be emulated withbiased
andready(())
.complete
is same aselse
intokio::select!
. tokio::select!
strips the pattern using in refutability throughproc_marco
. This avoid false negative compilation error.async_select::select!
is dependency free and henceno_std
compatible.
§Polling order
By default, the polling order of each branch is indeterminate. Use biased;
to poll
sequentially if desired.
use async_select::select;
use core::future::{pending, ready};
async fn poll_sequentially() {
let r = select! {
biased;
default => unreachable!(),
_ = pending() => unreachable!(),
_ = pending() => unreachable!(),
v = ready(5) => v,
v = ready(6) => v,
v = ready(7) => v,
};
assert_eq!(r, 5);
}
§Efficiency
select!
blindly Future:poll
all enabled futures without checking for waking branch.
§Examples
use async_select::select;
use core::future::{pending, ready};
async fn on_ready() {
let r = select! {
_ = pending() => unreachable!(),
v = ready(5) => v,
default => unreachable!(),
};
assert_eq!(r, 5);
}