# crossbeam-ring-channel
A small Rust crate that adds a ring-buffer channel alongside `crossbeam-channel`, plus a `Select` wrapper that can mix ring receivers with standard crossbeam-channel send/recv operations.
## What it provides
- `ring_bounded(capacity)`: a bounded, ring-buffer channel.
- `RingSender` / `RingReceiver`: sender/receiver halves with familiar methods.
- `Select` + `select!` / `select_biased!`: crossbeam-style selection that works with ring receivers and crossbeam-channel send/recv operations.
## Semantics
- The ring channel is **bounded** and **non-blocking on send**.
- When full, `send` **evicts the oldest item** in the buffer to make room for the new one.
- `recv` blocks until an item is available or all senders are dropped.
## Installation
Add to your `Cargo.toml`:
```toml
[dependencies]
crossbeam-ring-channel = "0.1"
crossbeam-channel = "0.5" # needed if you use crossbeam-channel receivers/senders in Select
```
## Usage
Basic ring channel:
```rust
use crossbeam_ring_channel::ring_bounded;
let (tx, rx) = ring_bounded(2);
// Sends never block; the oldest item is dropped when full.
tx.send("a").unwrap();
tx.send("b").unwrap();
tx.send("c").unwrap();
assert_eq!(rx.recv().unwrap(), "b");
assert_eq!(rx.recv().unwrap(), "c");
```
Selecting over ring receivers and crossbeam-channel receivers:
```rust
use crossbeam_channel::unbounded;
use crossbeam_ring_channel::{ring_bounded, Select};
let (ring_tx, ring_rx) = ring_bounded::<i32>(1);
let (tx, rx) = unbounded::<i32>();
ring_tx.send(1).unwrap();
tx.send(2).unwrap();
let mut sel = Select::new();
let ring_idx = sel.recv(&ring_rx);
let cb_idx = sel.recv(&rx);
let oper = sel.select();
match oper.index() {
i if i == ring_idx => {
let value = oper.recv(&ring_rx).unwrap();
assert_eq!(value, 1);
}
i if i == cb_idx => {
let value = oper.recv(&rx).unwrap();
assert_eq!(value, 2);
}
_ => unreachable!(),
}
```
Macro selection:
```rust
use crossbeam_ring_channel::{ring_bounded, select};
let (tx, rx) = ring_bounded::<i32>(1);
tx.send(42).unwrap();
select! {
recv(rx) -> msg => {
assert_eq!(msg.unwrap(), 42);
},
}
```
## API overview
- `ring_bounded(size)`
- `RingSender<T>` / `RingReceiver<T>`
- `send`, `recv`, `try_recv`, `recv_timeout`
- `len`, `capacity`, `is_empty`, `is_full`, `same_channel`
- `Select` and `SelectedOperation`
- Macros: `select!`, `select_biased!`