lochan 0.1.0

Single-threaded (!Send), no_std, no-atomics async channels for thread-per-core runtimes: mpsc and oneshot, with non-blocking (try_*) and awaitable APIs.
Documentation

Single-threaded (!Send), no_std, no-atomics async channels for thread-per-core runtimes.

Overview

lochan is a family of single-threaded async channels for thread-per-core runtimes — compio, monoio, glommio, embassy, a tokio LocalSet, and the like. The handles hold Rc rather than Arc, so they are !Send (producer and consumer always live on one thread) and the implementation uses no atomics — making them strictly lighter than their Send counterparts (tokio, flume, futures) on a single-threaded executor. no_std + alloc.

  • mpsc — multi-producer, single-consumer. bounded (a fixed MaybeUninit ring) and unbounded (a segmented block-list that never reallocates). Non-blocking try_send / try_recv, plus awaitable send / recv.
  • oneshot — a single value sent once; the Receiver is itself a Future.

Every awaitable method returns a named Unpin + FusedFuture type, so it drops into select_biased! without .fuse() and can be stored in a hand-rolled driver state machine.

Installation

[dependencies]
lochan = "0.1"

For no_std, disable default features: lochan = { version = "0.1", default-features = false }.

Example

// mpsc — sync surface
let (tx, mut rx) = lochan::mpsc::bounded::<u32>(16);
tx.try_send(1).unwrap();
assert_eq!(rx.try_recv(), Ok(1));

// mpsc — async surface
tx.send(2).await.unwrap();
assert_eq!(rx.recv().await, Some(2));

// oneshot — the Receiver is the future
let (tx, rx) = lochan::oneshot::channel::<u32>();
tx.send(42).unwrap();
assert_eq!(rx.await, Ok(42));

Benchmarks

A throughput comparison against the other single-threaded (!Send) channel crates, local-sync and local-channel, measured with cargo bench (criterion). Each mpsc row buffers 1024 u32 values then drains them on a single task; oneshot times one create + send + receive. local-channel provides only an unbounded mpsc.

benchmark (1024 elements) lochan local-sync local-channel
mpsc unbounded — buffer + drain 6.5 µs · 158 Melem/s 6.5 µs · 158 Melem/s 6.4 µs · 160 Melem/s
mpsc bounded — buffer + drain 6.3 µs · 163 Melem/s 12.6 µs · 82 Melem/s
oneshot — create + send + recv 19.0 ns 19.6 ns

Indicative only — laptop run-to-run variance is ±10–15%, so compare within one cargo bench run rather than against the absolute figures. On that basis, lochan is on par with local-sync on the unbounded channel and on oneshot, and ~2× faster on the bounded channel (its fixed MaybeUninit ring beats local-sync's semaphore-gated bounded queue).

License

lochan is under the terms of both the MIT license and the Apache License (Version 2.0).

See LICENSE-APACHE, LICENSE-MIT for details.

Copyright (c) 2026 Al Liu.