use crate::loom::sync::atomic::{Ordering, fence};
use std::cell::UnsafeCell;
use std::mem::MaybeUninit;
pub struct Slot<T> {
value: UnsafeCell<MaybeUninit<T>>,
}
unsafe impl<T: Send> Send for Slot<T> {}
unsafe impl<T: Send> Sync for Slot<T> {}
impl<T> Slot<T> {
fn uninit() -> Self {
Slot {
value: UnsafeCell::new(MaybeUninit::uninit()),
}
}
}
pub struct Slotable;
impl<T: Copy> super::Slotable<T> for Slotable {
type Slot = Slot<T>;
type SlotArrayItem = Slot<T>;
fn boxed_uninit_single() -> Box<Self::Slot> {
Box::new(Slot::uninit())
}
fn create_boxed(value: T) -> Box<Self::Slot> {
Box::new(Slot {
value: UnsafeCell::new(MaybeUninit::new(value)),
})
}
fn read(slot: &Self::Slot, ordering: Ordering) -> MaybeUninit<T> {
let value = unsafe { slot.value.get().read_volatile() };
if ordering != Ordering::Relaxed {
fence(ordering);
}
value
}
fn write(slot: &Self::Slot, value: T, ordering: Ordering) {
if ordering != Ordering::Relaxed {
fence(ordering);
}
unsafe {
slot.value.get().write_volatile(MaybeUninit::new(value));
}
}
fn boxed_uninit_multiple(n: usize) -> Box<[Self::SlotArrayItem]> {
std::iter::repeat_with(Slot::uninit)
.take(n)
.collect::<Vec<_>>()
.into_boxed_slice()
}
fn index_in_array(items: &[Self::SlotArrayItem], index: usize) -> &Self::Slot {
&items[index]
}
}
crate::impl_channels!(crate::fast::Slotable, Copy);