use std::{
cell::UnsafeCell,
mem::MaybeUninit,
sync::atomic::{AtomicU32, Ordering},
};
pub(crate) struct ElemArr<T> {
lap: AtomicU32,
msg: UnsafeCell<MaybeUninit<T>>,
}
impl<T> Default for ElemArr<T> {
#[inline(always)]
fn default() -> Self {
Self {
lap: AtomicU32::new(0),
msg: UnsafeCell::new(MaybeUninit::uninit()),
}
}
}
impl<T> ElemArr<T> {
#[inline(always)]
pub(crate) fn load_lap(&self) -> u32 {
self.lap.load(Ordering::Acquire)
}
#[inline(always)]
pub(crate) fn write(&self, lap: u32, msg: T) {
unsafe {
self.msg.get().write(MaybeUninit::new(msg));
}
self.lap.store(lap, Ordering::Release);
}
#[inline(always)]
pub(crate) fn read(&self, lap: u32) -> T {
let msg: T;
unsafe {
msg = self.msg.get().read().assume_init();
}
self.lap.store(lap, Ordering::Release);
msg
}
#[inline(always)]
pub(crate) fn atom_lap(&self) -> *const AtomicU32 {
&self.lap
}
}
impl<T> Drop for ElemArr<T> {
fn drop(&mut self) {
unsafe {
let raw_data = self.msg.get_mut().as_mut_ptr();
if !raw_data.is_null() {
std::ptr::drop_in_place(raw_data);
}
}
}
}