# selectme
[](https://github.com/udoprog/selectme)
[](https://crates.io/crates/selectme)
[](https://docs.rs/selectme)
[](https://github.com/udoprog/selectme/actions?query=branch%3Amain)
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`:
```toml
selectme = "0.7.1"
```
## Examples
The following is a simple example showcasing two branches being polled
concurrently. For more documentation see [select!].
```rust
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")
}
};
```
## Entrypoint macros
This crate provides entrypoint attributes which are compatible with the ones
provided by Tokio through [`#[selectme::main]`][selectme-main] and
[`#[selectme::test]`][selectme-test] with one exception. They do not check
(because they cannot) which Tokio features are enabled and simply assumes
that you want to build a multithreaded runtime unless `flavor` is specified.
So why does this project provide entrypoint macros? Well, there's [a handful
of issues related to performance and ergonomics][tokio-entrypoints-pr] which
turns out to be quite hard to fix in Tokio proper since backwards
compatibility needs to be maintained. So until a Tokio `2.x` is released and
we can bake another breaking release. Until such a time, you can find those
macros here.
## 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.
```rust
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.
```rust
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::time::Duration;
use pin_project::pin_project;
use selectme::{Random, StaticSelect};
use tokio::time::{self, Sleep};
#[pin_project]
struct MyFuture {
#[pin]
select: StaticSelect>,
}
impl Future for MyFuture {
type Output = Option;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll {
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));
```
[inline!]: https://docs.rs/selectme/latest/selectme/macro.inline.html
[select!]: https://docs.rs/selectme/latest/selectme/macro.select.html
[Select]: https://docs.rs/selectme/latest/selectme/struct.Select.html
[selectme-main]: https://docs.rs/selectme/latest/selectme/attr.main.html
[selectme-test]: https://docs.rs/selectme/latest/selectme/attr.test.html
[StaticSelect]: https://docs.rs/selectme/latest/selectme/struct.StaticSelect.html
[tokio-entrypoints-pr]: https://github.com/tokio-rs/tokio/pull/4513