Skip to main content

Crate enso_channel

Crate enso_channel 

Source
Expand description

enso_channel

Bounded. Lock-free. Batch-native.

enso_channel is a batch-first concurrency primitive: a family of bounded, lock-free, ring-buffer channels designed for bursty, latency-sensitive systems.

The API is intentionally non-blocking: operations are exposed as try_* and surface backpressure/termination explicitly via errors (Full, Empty, Disconnected).

§Mental model

Instead of sending items one-by-one, producers typically:

  1. claim a contiguous range in the ring buffer,
  2. write into it,
  3. commit the range.

Receivers observe items via RAII guards/iterators; dropping them commits consumption.

§Misuse prevention (compile-time)

Batch receives return a guard that commits consumption on drop. To keep this sound, the guard is intentionally not an Iterator<Item = &T>.

use enso_channel::mpsc;
let (mut tx, mut rx) = mpsc::channel::<u64>(4);
tx.try_send(1).unwrap();
let batch = rx.try_recv_many(1).unwrap();
// `RecvIter` is not an iterator; use `batch.iter()` instead.
for v in batch {
    let _ = v;
}

References yielded by batch.iter() are tied to the borrow of the batch guard and cannot outlive it:

use enso_channel::mpsc;
let (mut tx, mut rx) = mpsc::channel::<u64>(4);
tx.try_send(1).unwrap();

let r: &u64 = {
    let batch = rx.try_recv_many(1).unwrap();
    batch.iter().next().unwrap()
};
let _ = *r;

And you can’t commit (drop/finish) the guard while holding a reference from it:

use enso_channel::mpsc;
let (mut tx, mut rx) = mpsc::channel::<u64>(4);
tx.try_send(1).unwrap();

let batch = rx.try_recv_many(1).unwrap();
let first = batch.iter().next().unwrap();
batch.finish();
let _ = *first;

§Public API modules

  • mpsc: multi-producer, single-consumer
  • broadcast: lossless fixed-N fanout (each receiver sees every item)
  • mpmc: multi-producer, multi-consumer work distribution

§Non-goals

  • no blocking API
  • no async/await integration
  • no dynamic resizing
  • no built-in scheduling policy

§Lifecycle / shutdown (RAII)

This crate intentionally does not expose an explicit close()/terminate() API. Shutdown is expressed through normal Rust endpoint lifecycle:

  • dropping the last sender initiates shutdown; receivers may drain already-committed items and then observe Disconnected;
  • dropping the last receiver disconnects senders (subsequent sends return Disconnected).

§Concurrency caveat

Disconnection is eventual, not transactional. In concurrent code, an operation may still succeed while the peer endpoint is being dropped, and already-committed items may never be observed by the application.

Modules§

broadcast
Multi-publisher, multi-consumer broadcast channel.
errors
Error types returned by non-blocking try_* channel operations.
mpmc
Multi-producer, multi-consumer (MPMC) work distribution channel.
mpsc
Multi-producer, single-consumer (MPSC) channel.