macro_rules! select {
(biased; $($token:tt)*) => { ... };
($($token:tt)*) => { ... };
}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.
defaultclause 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
completeordefaultin case of nocomplete.
§Panics
- Panic when all futures are disabled or completed and there is no
defaultorcomplete.
§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. See https://github.com/tokio-rs/tokio/pull/6555. - There is no
defaultcounterpart intokio::select!. But it could be emulated withbiasedandready(()).completeis same aselseintokio::select!. async_select::select!depends only onproc_macromacros and hence the generated code isno_stdcompatible.
§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);
}