# async-oneshot [![License](https://img.shields.io/crates/l/async-oneshot.svg)](https://github.com/irrustible/async-oneshot/blob/main/LICENSE) [![Package](https://img.shields.io/crates/v/async-oneshot.svg)](https://crates.io/crates/async-oneshot) [![Documentation](https://docs.rs/async-oneshot/badge.svg)](https://docs.rs/async-oneshot) A fast, small, full-featured, async-aware oneshot channel. Features: * Blazing fast! See `Performance` section below. * Tiny code, only one dependency and a lightning quick build. * Complete `no_std` support (with `alloc` for `Arc`). * Unique feature: sender may wait for a receiver to be waiting. ## Usage ```rust #[test] fn success_one_thread() { let (s,r) = oneshot::(); assert_eq!((), s.send(true).unwrap()); assert_eq!(Ok(true), future::block_on(r)); } ``` ## Performance async-oneshot comes with a benchmark suite which you can run with `cargo bench`. All benches are single-threaded and take double digit nanoseconds on my machine. async benches use `futures_lite::future::block_on` as an executor. ### Numbers from my machine Here are benchmark numbers from my primary machine, a Ryzen 9 3900X running alpine linux 3.12 that I attempted to peg at maximum cpu: ``` create_destroy time: [51.596 ns 51.710 ns 51.835 ns] send/success time: [13.080 ns 13.237 ns 13.388 ns] send/closed time: [25.304 ns 25.565 ns 25.839 ns] try_recv/success time: [26.136 ns 26.246 ns 26.335 ns] try_recv/empty time: [10.764 ns 11.161 ns 11.539 ns] try_recv/closed time: [27.048 ns 27.159 ns 27.248 ns] async.recv/success time: [30.532 ns 30.774 ns 31.011 ns] async.recv/closed time: [28.112 ns 28.208 ns 28.287 ns] async.wait/success time: [56.449 ns 56.603 ns 56.737 ns] async.wait/closed time: [34.014 ns 34.154 ns 34.294 ns] ``` In short, we are very fast. Close to optimal, I think. ### Compared to other libraries The oneshot channel in `futures` isn't very fast by comparison. Tokio put up an excellent fight and made us work hard to improve. In general I'd say we're slightly faster overall, but it's incredibly tight. ## Note on safety This crate uses UnsafeCell and manually synchronises with atomic bitwise ops for performance. We believe it is correct, but we would welcome more eyes on it. # See Also * [async-oneshot-local](https://github.com/irrustible/async-oneshot-local) (single threaded) * [async-spsc](https://github.com/irrustible/async-spsc) (SPSC) * [async-channel](https://github.com/stjepang/async-channel) (MPMC) ## Note on benchmarking The benchmarks are synthetic and a bit of fun. ## Changelog ### v0.5.0 Breaking changes: * Make `Sender.send()` only take a mut ref instead of move. ### v0.4.2 Improvements: * Added some tests to cover repeated fix released in last version. * Inline more aggressively for some nice benchmark boosts. ### v0.4.1 Fixes: * Remove some overzealous `debug_assert`s that caused crashes in development in case of repeated waking. Thanks @nazar-pc! Improvements: * Better benchmarks, based on criterion. ### v0.4.0 Breaking changes: * `Sender.wait()`'s function signature has changed to be a non-`async fn` returning an `impl Future`. This reduces binary size, runtime and possibly memory usage too. Thanks @zserik! Fixes: * Race condition where the sender closes in a narrow window during receiver poll and doesn't wake the Receiver. Thanks @zserik! Improvements: * Static assertions. Thanks @zserik! ### v0.3.3 Improvements: * Update `futures-micro` and improve the tests ### v0.3.2 Fixes: * Segfault when dropping receiver. Caused by a typo, d'oh! Thanks @boardwalk! ### v0.3.1 Improvements: * Remove redundant use of ManuallyDrop with UnsafeCell. Thanks @cynecx! ### v0.3.0 Improvements: * Rewrote, benchmarked and optimised. ### v0.2.0 * First real release. ## Copyright and License Copyright (c) 2020 James Laver, async-oneshot contributors. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.