oneringbuf 0.7.0

A lock-free single-producer, single-consumer (SPSC) ring buffer with in-place mutability, asynchronous support, and virtual memory optimisation.
Documentation
extern crate alloc;

use crate::{common_def, get_buf};
use oneringbuf::ORBIterator;

common_def!();

#[test]
fn test_push_work_pop_single() {
    let mut buf = get_buf!(SharedMut);
    let (mut prod, mut work, mut cons) = buf.split_mut();

    assert_eq!(prod.available(), BUFFER_SIZE - 1);
    assert_eq!(work.available(), 0);
    assert_eq!(cons.available(), 0);

    for i in 0..BUFFER_SIZE - 1 {
        let _ = prod.push(i);
    }
    assert_eq!(prod.available(), 0);
    assert_eq!(work.available(), BUFFER_SIZE - 1);
    assert_eq!(cons.available(), 0);

    for _ in 0..BUFFER_SIZE - 1 {
        if let Some(data) = work.get_mut() {
            *data += 1;
            unsafe { work.advance(1) };
        }
    }
    assert_eq!(prod.available(), 0);
    assert_eq!(work.available(), 0);
    assert_eq!(cons.available(), BUFFER_SIZE - 1);

    for i in 0..BUFFER_SIZE - 1 {
        assert_eq!(cons.pop().unwrap(), i + 1);
    }

    assert_eq!(prod.available(), BUFFER_SIZE - 1);
    assert_eq!(work.available(), 0);
    assert_eq!(cons.available(), 0);
}

#[test]
fn test_push_work_pop_slice() {
    let mut buf = get_buf!(SharedMut);
    let (mut prod, mut work, mut cons) = buf.split_mut();

    let slice = (0..BUFFER_SIZE - 1).collect::<Vec<usize>>();

    assert_eq!(prod.available(), BUFFER_SIZE - 1);
    assert_eq!(work.available(), 0);
    assert_eq!(cons.available(), 0);

    prod.push_slice(&slice);

    assert_eq!(prod.available(), 0);
    assert_eq!(work.available(), BUFFER_SIZE - 1);
    assert_eq!(cons.available(), 0);

    #[cfg(not(all(feature = "vmem", unix)))]
    if let Some((h, t)) = work.get_mut_slice_exact(BUFFER_SIZE - 1) {
        for i in h.iter_mut().chain(t) {
            *i += 1;
        }
        unsafe { work.advance(BUFFER_SIZE - 1) };
    }
    #[cfg(all(feature = "vmem", unix))]
    if let Some(s) = work.get_mut_slice_exact(BUFFER_SIZE - 1) {
        for i in s {
            *i += 1;
        }
        unsafe { work.advance(BUFFER_SIZE - 1) };
    }

    assert_eq!(prod.available(), 0);
    assert_eq!(work.available(), 0);
    assert_eq!(cons.available(), BUFFER_SIZE - 1);

    #[cfg(not(all(feature = "vmem", unix)))]
    if let Some((h, t)) = cons.peek_slice(BUFFER_SIZE - 1) {
        for (consumed, i) in [h, t].concat().iter().zip(slice) {
            assert_eq!(*consumed, i + 1);
        }
    }
    #[cfg(all(feature = "vmem", unix))]
    if let Some(s) = cons.peek_slice(BUFFER_SIZE - 1) {
        for (consumed, i) in s.iter().zip(slice) {
            assert_eq!(*consumed, i + 1);
        }
    }

    unsafe { cons.advance(BUFFER_SIZE - 1) };

    assert_eq!(prod.available(), BUFFER_SIZE - 1);
    assert_eq!(work.available(), 0);
    assert_eq!(cons.available(), 0);
}

#[test]
fn test_reset() {
    let mut buf = get_buf!(SharedMut);
    let (mut prod, mut work, mut cons) = buf.split_mut();

    let two_thirds_slice = (0..BUFFER_SIZE / 3 * 2).collect::<Vec<usize>>();
    let slice = (0..BUFFER_SIZE - 1).collect::<Vec<usize>>();

    assert_eq!(prod.available(), BUFFER_SIZE - 1);
    assert_eq!(work.available(), 0);
    assert_eq!(cons.available(), 0);

    prod.push_slice(&two_thirds_slice);

    assert_eq!(prod.available(), BUFFER_SIZE / 3);
    assert_eq!(work.available(), BUFFER_SIZE / 3 * 2);
    assert_eq!(cons.available(), 0);

    unsafe { work.advance(BUFFER_SIZE / 3) };

    assert_eq!(prod.available(), BUFFER_SIZE / 3);
    assert_eq!(work.available(), BUFFER_SIZE / 3);
    assert_eq!(cons.available(), BUFFER_SIZE / 3);

    work.reset_index();

    assert_eq!(prod.available(), BUFFER_SIZE / 3);
    assert_eq!(work.available(), 0);
    assert_eq!(cons.available(), BUFFER_SIZE / 3 * 2);

    cons.reset_index();

    assert_eq!(prod.available(), BUFFER_SIZE - 1);
    assert_eq!(work.available(), 0);
    assert_eq!(cons.available(), 0);

    prod.push_slice(&slice);

    assert_eq!(prod.available(), 0);
    assert_eq!(work.available(), BUFFER_SIZE - 1);
    assert_eq!(cons.available(), 0);

    work.reset_index();

    assert_eq!(prod.available(), 0);
    assert_eq!(work.available(), 0);
    assert_eq!(cons.available(), BUFFER_SIZE - 1);
}