# selectme [github](https://github.com/udoprog/selectme) [crates.io](https://crates.io/crates/selectme) [docs.rs](https://docs.rs/selectme) [build status](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