# unsync [github](https://github.com/udoprog/unsync) [crates.io](https://crates.io/crates/unsync) [docs.rs](https://docs.rs/unsync) [build status](https://github.com/udoprog/unsync/actions?query=branch%3Amain) Unsynchronized synchronization primitives for async Rust. This crate provides a fairly simple set of synchronization primitives which are explicitly `!Send` and `!Sync`. This makes them useful for use in singlethreaded systems like [yew]. You can think of this as a modern replacement to the now-deprecated [futures::unsync] module.
## Why do you want `!Send` / `!Sync` synchronization primitives? Having unsynchronized sync primitives might seem *weird* since they are largely used for inter-task communication across threads. The need for such primitives increase as we are seeing more singlethreaded systems like [yew] mature and are receiving richer support for async programming. In order to make them as efficient as possible it's useful that they are written with unsynchronized systems and constraints in mind so that they don't have to make use of atomics and locks. The overhead of synchronization in real systems should be minor because of the role channels play in typical applications and they are optimized for uncontended use. But unsynchronized code still has the ability to optimize better for both performance and size. In one of my applications replacing the use of `tokio::sync::oneshot` with `unsync::oneshot` reduced the size of the resulting binary by 30kb (10kb when optimized with `wasm-opt`). Synthetic benchmarks in this project hints at the unsync channels being about twice as fast for optimized builds when used inside of a [LocalSet]. I haven't dug too deep into the specifics of why this is, but as long as this is the case I'd like to have access to drop in replacements allowing someone to tap into these benefits. [yew]: [LocalSet]: https://docs.rs/tokio/latest/tokio/task/struct.LocalSet.html
## Usage Add the following to your `Cargo.toml`: ```toml unsync = "0.1.1" ```
## Examples ```rust use unsync::spsc::{channel, Sender, Receiver}; use std::error::Error; use tokio::task; async fn receiver(mut rx: Receiver) -> Vec { let mut out = Vec::new(); while let Some(m) = rx.recv().await { out.push(m); } out } async fn sender(mut tx: Sender) -> Result<(), Box> { for n in 0..1000 { tx.send(n).await?; } Ok(()) } async fn run() -> Result<(), Box> { let (tx, rx) = channel(4); let _ = task::spawn_local(sender(tx)); let out = task::spawn_local(receiver(rx)).await?; let expected = (0..1000).collect::>(); assert_eq!(out, expected); Ok(()) } ``` [futures::unsync]: