Expand description
A fast and fair select! implementation for asynchronous programming.
See the select! or inline! macros for documentation.
Usage
Add the following to your Cargo.toml
:
selectme = "0.4.4"
Examples
The following is a simple example showcasing two branches being polled concurrently. For more documentation see select!.
async fn do_stuff_async() {
// work here
}
async fn more_async_work() {
// work here
}
selectme::select! {
_ = do_stuff_async() => {
println!("do_stuff_async() completed first")
}
_ = more_async_work() => {
println!("more_async_work() completed first")
}
};
The inline!
macro
The inline! macro provides an inlined variant of the select! macro.
Instead of awaiting directly it evaluates to an instance of the Select or StaticSelect allowing for more efficient multiplexing and complex control flow.
When combined with the static;
option it performs the least amount of
magic possible to multiplex multiple asynchronous operations making it
suitable for efficient and custom abstractions.
use std::time::Duration;
use tokio::time;
async fn async_operation() -> u32 {
// work here
}
let output = selectme::inline! {
output = async_operation() => Some(output),
() = time::sleep(Duration::from_secs(5)) => None,
}.await;
match output {
Some(output) => {
assert_eq!(output, 42);
}
None => {
panic!("operation timed out!")
}
}
The more interesting trick is producing a StaticSelect through the
static;
option which can be properly named and used inside of another
future.
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::time::Duration;
use pin_project::pin_project;
use selectme::StaticSelect;
use tokio::time::{self, Sleep};
#[pin_project]
struct MyFuture {
#[pin]
select: StaticSelect<(Sleep, Sleep), Option<u32>>,
}
impl Future for MyFuture {
type Output = Option<u32>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
this.select.poll_next(cx)
}
}
let s1 = time::sleep(Duration::from_millis(100));
let s2 = time::sleep(Duration::from_millis(200));
let my_future = MyFuture {
select: selectme::inline! {
static;
() = s1 => Some(1),
_ = s2 => Some(2),
else => None,
}
};
assert_eq!(my_future.await, Some(1));
Macros
Waits on multiple concurrent branches, returning when the first branch completes, cancelling the remaining branches.