selectme

github crates.io docs.rs build status

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.4.3"


Examples

The following is a simple example showcasing two branches being polled concurrently. For more documentation see [select!].

```rust async fn dostuffasync() { // work here }

async fn moreasyncwork() { // work here }

selectme::select! { _ = dostuffasync() => { println!("dostuffasync() completed first") } _ = moreasyncwork() => { println!("moreasyncwork() 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.

```rust use std::time::Duration; use tokio::time;

async fn async_operation() -> u32 { // work here }

let output = selectme::inline! { output = asyncoperation() => Some(output), () = time::sleep(Duration::fromsecs(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 pinproject::pinproject; use selectme::StaticSelect; use tokio::time::{self, Sleep};

[pin_project]

struct MyFuture { #[pin] select: StaticSelect<(Sleep, Sleep), Option>, }

impl Future for MyFuture { type Output = Option;

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::frommillis(100)); let s2 = time::sleep(Duration::frommillis(200));

let my_future = MyFuture { select: selectme::inline! { static;

    () = s1 => Some(1),
    _ = s2 => Some(2),
    else => None,
}

};

asserteq!(myfuture.await, Some(1)); ```

License: MIT/Apache-2.0