quickring 0.1.0

A very fast, lock-free SPSC ring buffer.
Documentation
use quickring::RingBuffer;
use std::net::UdpSocket;
use std::thread;
use std::time::Duration;

fn main() -> std::io::Result<()> {
    let server_thread = run_udp_server();
    let client_thread = run_udp_client();

    // Wait for both threads (will run indefinitely)
    let _ = server_thread.join();
    let _ = client_thread.join();

    Ok(())
}

fn run_udp_server() -> thread::JoinHandle<()> {
    // =====================
    // UDP Server Thread
    // =====================
    thread::spawn(|| {
        let socket = UdpSocket::bind("127.0.0.1:9000").expect("Server bind failed");
        println!("Server listening on 127.0.0.1:9000");

        let mut buf = [0u8; 1024];

        // Wait for first packet to learn client address
        let (n, client_addr) = socket.recv_from(&mut buf).expect("recv_from failed");
        println!("Server: client connected from {}", client_addr);
        println!("Server received initial packet: {:?}", &buf[..n]);

        // Send dummy data repeatedly
        let mut counter = 0;
        loop {
            let msg = format!("packet {}\n", counter);
            socket
                .send_to(msg.as_bytes(), client_addr)
                .expect("send_to failed");
            counter += 1;
            thread::sleep(Duration::from_millis(100));
        }
    })
}

fn run_udp_client() -> thread::JoinHandle<()> {
    // =====================
    // UDP Client Thread
    // =====================
    thread::spawn(|| {
        // Bind to ephemeral port
        let socket = UdpSocket::bind("127.0.0.1:0").expect("Client bind failed");
        socket
            .connect("127.0.0.1:9000")
            .expect("Client connect failed");

        // Let server know we're here
        socket.send(b"hello").expect("Initial send failed");

        // Ring buffer for packets
        const CAPACITY: usize = 1 << 13; // 8192

        let rb = RingBuffer::<Vec<u8>, CAPACITY>::new();
        let (mut prod, mut cons) = rb.split();

        // Receiver thread: reads UDP into ring buffer
        let recv_thread = thread::spawn(move || {
            let mut buf = [0u8; 2048];

            loop {
                match socket.recv(&mut buf) {
                    Ok(n) => {
                        let packet = buf[..n].to_vec();
                        if !prod.push(packet) {
                            eprintln!("Ring buffer full, dropping packet");
                        }
                    }
                    Err(e) => {
                        eprintln!("recv error: {}", e);
                        break;
                    }
                }
            }
        });

        // Consumer loop: read packets from ring buffer
        loop {
            if let Some(packet) = cons.pop() {
                let text = String::from_utf8_lossy(&packet);
                print!("Client got: {}", text);
            } else {
                std::thread::yield_now();
            }
        }

        let _ = recv_thread.join();
    })
}