Const assert and switch to u8 sizes

This commit is contained in:
Vinay Chandra Dommeti 2021-05-07 13:01:53 -07:00
parent b5dd0afa4c
commit e68383be09
No known key found for this signature in database
GPG Key ID: 409C3C9C44DCD4E1

View File

@ -85,10 +85,10 @@
use core::{cell::UnsafeCell, mem::MaybeUninit}; use core::{cell::UnsafeCell, mem::MaybeUninit};
#[cfg(armv6m)] #[cfg(armv6m)]
use atomic_polyfill::{AtomicUsize, Ordering}; use atomic_polyfill::{AtomicU8, Ordering};
#[cfg(not(armv6m))] #[cfg(not(armv6m))]
use core::sync::atomic::{AtomicUsize, Ordering}; use core::sync::atomic::{AtomicU8, Ordering};
/// MPMC queue with a capability for 2 elements. /// MPMC queue with a capability for 2 elements.
pub type Q2<T> = MpMcQueue<T, 2>; pub type Q2<T> = MpMcQueue<T, 2>;
@ -109,18 +109,24 @@ pub type Q32<T> = MpMcQueue<T, 32>;
pub type Q64<T> = MpMcQueue<T, 64>; pub type Q64<T> = MpMcQueue<T, 64>;
/// MPMC queue with a capacity for N elements /// MPMC queue with a capacity for N elements
/// The max value of N is u8::MAX - 1.
pub struct MpMcQueue<T, const N: usize> { pub struct MpMcQueue<T, const N: usize> {
buffer: UnsafeCell<[Cell<T>; N]>, buffer: UnsafeCell<[Cell<T>; N]>,
dequeue_pos: AtomicUsize, dequeue_pos: AtomicU8,
enqueue_pos: AtomicUsize, enqueue_pos: AtomicU8,
} }
impl<T, const N: usize> MpMcQueue<T, N> { impl<T, const N: usize> MpMcQueue<T, N> {
const MASK: usize = N - 1; const MASK: u8 = (N - 1) as u8;
const EMPTY_CELL: Cell<T> = Cell::new(0); const EMPTY_CELL: Cell<T> = Cell::new(0);
const ASSERT: [(); 1] = [()];
/// Creates an empty queue /// Creates an empty queue
pub const fn new() -> Self { pub const fn new() -> Self {
// Const assert on size.
Self::ASSERT[!(N < (u8::MAX as usize)) as usize];
let mut cell_count = 0; let mut cell_count = 0;
let mut result_cells: [Cell<T>; N] = [Self::EMPTY_CELL; N]; let mut result_cells: [Cell<T>; N] = [Self::EMPTY_CELL; N];
@ -131,8 +137,8 @@ impl<T, const N: usize> MpMcQueue<T, N> {
Self { Self {
buffer: UnsafeCell::new(result_cells), buffer: UnsafeCell::new(result_cells),
dequeue_pos: AtomicUsize::new(0), dequeue_pos: AtomicU8::new(0),
enqueue_pos: AtomicUsize::new(0), enqueue_pos: AtomicU8::new(0),
} }
} }
@ -160,19 +166,19 @@ unsafe impl<T, const N: usize> Sync for MpMcQueue<T, N> where T: Send {}
struct Cell<T> { struct Cell<T> {
data: MaybeUninit<T>, data: MaybeUninit<T>,
sequence: AtomicUsize, sequence: AtomicU8,
} }
impl<T> Cell<T> { impl<T> Cell<T> {
const fn new(seq: usize) -> Self { const fn new(seq: usize) -> Self {
Self { Self {
data: MaybeUninit::uninit(), data: MaybeUninit::uninit(),
sequence: AtomicUsize::new(seq), sequence: AtomicU8::new(seq as u8),
} }
} }
} }
unsafe fn dequeue<T>(buffer: *mut Cell<T>, dequeue_pos: &AtomicUsize, mask: usize) -> Option<T> { unsafe fn dequeue<T>(buffer: *mut Cell<T>, dequeue_pos: &AtomicU8, mask: u8) -> Option<T> {
let mut pos = dequeue_pos.load(Ordering::Relaxed); let mut pos = dequeue_pos.load(Ordering::Relaxed);
let mut cell; let mut cell;
@ -209,8 +215,8 @@ unsafe fn dequeue<T>(buffer: *mut Cell<T>, dequeue_pos: &AtomicUsize, mask: usiz
unsafe fn enqueue<T>( unsafe fn enqueue<T>(
buffer: *mut Cell<T>, buffer: *mut Cell<T>,
enqueue_pos: &AtomicUsize, enqueue_pos: &AtomicU8,
mask: usize, mask: u8,
item: T, item: T,
) -> Result<(), T> { ) -> Result<(), T> {
let mut pos = enqueue_pos.load(Ordering::Relaxed); let mut pos = enqueue_pos.load(Ordering::Relaxed);