[go: up one dir, main page]

heapless 0.4.3

`static` friendly data structures that don't require dynamic memory allocation
Documentation
#![deny(warnings)]

extern crate generic_array;
extern crate heapless;
extern crate scoped_threadpool;

use std::thread;

use generic_array::typenum::Unsigned;
use heapless::consts::*;
use heapless::spsc;
use scoped_threadpool::Pool;

#[test]
fn once() {
    static mut RB: Option<spsc::Queue<i32, U4>> = None;
    unsafe { RB = Some(spsc::Queue::new()) };

    let rb = unsafe { RB.as_mut().unwrap() };

    rb.enqueue(0).unwrap();

    let (mut p, mut c) = rb.split();

    p.enqueue(1).unwrap();

    thread::spawn(move || {
        p.enqueue(1).unwrap();
    });

    thread::spawn(move || {
        c.dequeue().unwrap();
    });
}

#[test]
fn twice() {
    static mut RB: Option<spsc::Queue<i32, U4>> = None;
    unsafe { RB = Some(spsc::Queue::new()) };

    let rb = unsafe { RB.as_mut().unwrap() };

    rb.enqueue(0).unwrap();
    rb.enqueue(1).unwrap();

    let (mut p, mut c) = rb.split();

    thread::spawn(move || {
        p.enqueue(2).unwrap();
        p.enqueue(3).unwrap();
    });

    thread::spawn(move || {
        c.dequeue().unwrap();
        c.dequeue().unwrap();
    });
}

#[test]
fn scoped() {
    let mut rb: spsc::Queue<i32, U4> = spsc::Queue::new();

    rb.enqueue(0).unwrap();

    {
        let (mut p, mut c) = rb.split();

        Pool::new(2).scoped(move |scope| {
            scope.execute(move || {
                p.enqueue(1).unwrap();
            });

            scope.execute(move || {
                c.dequeue().unwrap();
            });
        });
    }

    rb.dequeue().unwrap();
}

#[test]
fn contention() {
    type N = U1024;

    let mut rb: spsc::Queue<u8, N> = spsc::Queue::new();

    {
        let (mut p, mut c) = rb.split();

        Pool::new(2).scoped(move |scope| {
            scope.execute(move || {
                let mut sum: u32 = 0;

                for i in 0..(2 * N::to_u32()) {
                    sum = sum.wrapping_add(i);
                    while let Err(_) = p.enqueue(i as u8) {}
                }

                println!("producer: {}", sum);
            });

            scope.execute(move || {
                let mut sum: u32 = 0;

                for _ in 0..(2 * N::to_u32()) {
                    loop {
                        match c.dequeue() {
                            Some(v) => {
                                sum = sum.wrapping_add(v as u32);
                                break;
                            }
                            _ => {}
                        }
                    }
                }

                println!("consumer: {}", sum);
            });
        });
    }

    assert!(rb.is_empty());
}

#[test]
fn unchecked() {
    type N = U1024;

    let mut rb: spsc::Queue<u8, N> = spsc::Queue::new();

    for _ in 0..N::to_usize() / 2 {
        rb.enqueue(1).unwrap();
    }

    {
        let (mut p, mut c) = rb.split();

        Pool::new(2).scoped(move |scope| {
            scope.execute(move || {
                for _ in 0..N::to_usize() / 2 {
                    unsafe {
                        p.enqueue_unchecked(2);
                    }
                }
            });

            scope.execute(move || {
                let mut sum: usize = 0;

                for _ in 0..N::to_usize() / 2 {
                    sum = sum.wrapping_add(usize::from(unsafe { c.dequeue_unchecked() }));
                }

                assert_eq!(sum, N::to_usize() / 2);
            });
        });
    }

    assert_eq!(rb.len(), N::to_usize() / 2);
}

#[test]
fn len_properly_wraps() {
    type N = U3;
    let mut rb: spsc::Queue<u8, N> = spsc::Queue::new();

    rb.enqueue(1).unwrap();
    assert_eq!(rb.len(), 1);
    rb.dequeue();
    assert_eq!(rb.len(), 0);
    rb.enqueue(2).unwrap();
    assert_eq!(rb.len(), 1);
    rb.enqueue(3).unwrap();
    assert_eq!(rb.len(), 2);
    rb.enqueue(4).unwrap();
    assert_eq!(rb.len(), 3);
}

#[test]
fn iterator_properly_wraps() {
    type N = U3;
    let mut rb: spsc::Queue<u8, N> = spsc::Queue::new();

    rb.enqueue(1).unwrap();
    rb.dequeue();
    rb.enqueue(2).unwrap();
    rb.enqueue(3).unwrap();
    rb.enqueue(4).unwrap();
    let expected = [2, 3, 4];
    let mut actual = [0, 0, 0];
    for (idx, el) in rb.iter().enumerate() {
        actual[idx] = *el;
    }
    assert_eq!(expected, actual)
}