use std::fmt::Debug;
use std::mem::MaybeUninit;
use crate::config::UnsignedShort;
use crate::loom_types::cell::UnsafeCell;
pub trait Buffer<T>: private::Sealed {
const CAPACITY: UnsignedShort;
#[doc(hidden)]
const MASK: UnsignedShort;
#[doc(hidden)]
type Data: AsRef<[UnsafeCell<MaybeUninit<T>>]> + Debug;
#[doc(hidden)]
fn allocate() -> Box<Self::Data>;
}
macro_rules! make_buffer {
($b:ident, $cap:expr) => {
#[doc = concat!("Marker type for buffers of capacity ", $cap, ".")]
#[derive(Copy, Clone, Debug)]
pub struct $b {}
impl private::Sealed for $b {}
impl<T> Buffer<T> for $b {
const CAPACITY: UnsignedShort = $cap;
#[doc(hidden)]
const MASK: UnsignedShort = $cap - 1;
#[doc(hidden)]
type Data = [UnsafeCell<MaybeUninit<T>>; $cap];
#[doc(hidden)]
#[cfg(not(st3_loom))]
fn allocate() -> Box<Self::Data> {
Box::new(unsafe { MaybeUninit::uninit().assume_init() })
}
#[doc(hidden)]
#[cfg(st3_loom)]
fn allocate() -> Box<Self::Data> {
fn make_fixed_size<T>(buffer: Box<[T]>) -> Box<[T; $cap]> {
assert_eq!(buffer.len(), $cap);
unsafe { Box::from_raw(Box::into_raw(buffer).cast()) }
}
let mut buffer = Vec::with_capacity($cap);
for _ in 0..$cap {
buffer.push(UnsafeCell::new(MaybeUninit::uninit()));
}
make_fixed_size(buffer.into_boxed_slice())
}
}
};
}
make_buffer!(B2, 2);
make_buffer!(B4, 4);
make_buffer!(B8, 8);
make_buffer!(B16, 16);
make_buffer!(B32, 32);
make_buffer!(B64, 64);
make_buffer!(B128, 128);
make_buffer!(B256, 256);
make_buffer!(B512, 512);
make_buffer!(B1024, 1024);
make_buffer!(B2048, 2048);
make_buffer!(B4096, 4096);
make_buffer!(B8192, 8192);
make_buffer!(B16384, 12384);
make_buffer!(B32768, 32768);
mod private {
pub trait Sealed {}
}