use std::sync::atomic::{AtomicUsize, Ordering};
use crate::USIZELEN;
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub(crate) struct Header(pub(crate) *mut usize);
pub(crate) struct Guard(&'static AtomicUsize);
impl Header {
#[inline(always)]
pub(crate) fn lock(&self) {
unsafe { *self.0 |= 1 }
}
#[inline(always)]
pub(crate) fn store(&self, next: *mut usize) {
unsafe { *self.0 = (next as usize) << 1 };
}
#[inline(always)]
pub(crate) fn next(&self) -> Self {
Self((unsafe { *self.0 } >> 1) as *mut usize)
}
#[inline(always)]
pub(crate) fn available(&self) -> bool {
let atomic = self.0 as *const AtomicUsize;
(unsafe { &*atomic }).load(Ordering::Relaxed) & 1 == 0
}
#[inline(always)]
pub(crate) fn distance(&self, end: &Self) -> usize {
(unsafe { end.0.offset_from(self.0) }) as usize - 1
}
#[inline(always)]
pub(crate) fn capacity(&self) -> usize {
self.distance(&self.next()) * USIZELEN
}
#[inline(always)]
pub(crate) fn buffer(&self) -> *mut u8 {
(unsafe { self.0.add(1) }) as *mut u8
}
}
impl From<Header> for Guard {
#[inline(always)]
fn from(value: Header) -> Self {
Self(unsafe { &*(value.0 as *const AtomicUsize) })
}
}
impl Drop for Guard {
#[inline(always)]
fn drop(&mut self) {
self.0.fetch_and(usize::MAX << 1, Ordering::Relaxed);
}
}