use crossbeam_channel::{bounded, Receiver, Sender};
pub const C2G_IN_CAPACITY: usize = 256;
pub const C2G_OUT_CAPACITY: usize = 256;
#[derive(Debug, Clone)]
pub struct RingChannels<I, O> {
pub in_tx: Sender<I>,
pub in_rx: Receiver<I>,
pub out_tx: Sender<O>,
pub out_rx: Receiver<O>,
}
impl<I, O> RingChannels<I, O> {
pub fn new() -> Self {
Self::with_capacities(C2G_IN_CAPACITY, C2G_OUT_CAPACITY)
}
pub fn with_capacities(in_cap: usize, out_cap: usize) -> Self {
let (in_tx, in_rx) = bounded(in_cap);
let (out_tx, out_rx) = bounded(out_cap);
Self {
in_tx,
in_rx,
out_tx,
out_rx,
}
}
}
impl<I, O> Default for RingChannels<I, O> {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn capacities_match_c_constants() {
assert_eq!(C2G_IN_CAPACITY, 256);
assert_eq!(C2G_OUT_CAPACITY, 256);
}
#[test]
fn fifo_ordering_is_preserved() {
let chans: RingChannels<u32, ()> = RingChannels::new();
for i in 0..16u32 {
chans.in_tx.send(i).unwrap();
}
for i in 0..16u32 {
assert_eq!(chans.in_rx.recv().unwrap(), i);
}
}
#[test]
fn bounded_capacity_blocks_when_full() {
let chans: RingChannels<u32, ()> = RingChannels::with_capacities(2, 1);
chans.in_tx.send(1).unwrap();
chans.in_tx.send(2).unwrap();
assert!(chans.in_tx.try_send(3).is_err());
}
}