use core::cell::UnsafeCell;
use core::hint::spin_loop;
use core::ops::{Deref, DerefMut};
use core::sync::atomic::{AtomicBool, Ordering};
pub(crate) struct TTas<T: ?Sized> {
acquired: AtomicBool,
data: UnsafeCell<T>,
}
unsafe impl<T: ?Sized + Send> Send for TTas<T> {}
unsafe impl<T: ?Sized + Send> Sync for TTas<T> {}
impl<T> TTas<T> {
pub(crate) const fn new(data: T) -> Self {
Self {
acquired: AtomicBool::new(false),
data: UnsafeCell::new(data),
}
}
#[inline]
pub(crate) fn lock(&self) -> TTasGuard<'_, T> {
loop {
while self.acquired.load(Ordering::Relaxed) {
spin_loop();
}
if !self.acquired.swap(true, Ordering::Acquire) {
return TTasGuard { ttas: self };
}
}
}
}
pub(crate) struct TTasGuard<'a, T: ?Sized> {
ttas: &'a TTas<T>,
}
impl<T: ?Sized> Deref for TTasGuard<'_, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { &*self.ttas.data.get() }
}
}
impl<T: ?Sized> DerefMut for TTasGuard<'_, T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.ttas.data.get() }
}
}
impl<T: ?Sized> Drop for TTasGuard<'_, T> {
#[inline]
fn drop(&mut self) {
self.ttas.acquired.store(false, Ordering::Release);
}
}