use std::cell::*;
use std::mem::*;
use std::ops::*;
use std::sync::atomic::*;
#[derive(Debug, Default)]
pub struct ReadCell<T> {
inner: UnsafeCell<T>,
}
impl<T> ReadCell<T> {
#[inline(always)]
pub const fn new(value: T) -> Self {
Self {
inner: UnsafeCell::new(value),
}
}
}
impl<T> Deref for ReadCell<T> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &Self::Target {
unsafe { &*self.inner.get() }
}
}
#[derive(Debug, Default)]
pub struct RwCell<T> {
inner: ReadCell<RwCellInner<T>>,
}
impl<T> RwCell<T> {
#[inline(always)]
pub const fn new(value: T) -> Self {
Self {
inner: ReadCell::new(RwCellInner {
borrow_state: AtomicU16::new(0),
value: UnsafeCell::new(value),
}),
}
}
#[inline(always)]
pub fn borrow(&self) -> RwCellGuard<'_,T> {
unsafe {
Self::abort_if(
self.inner.borrow_state.fetch_add(1, Ordering::AcqRel) >= u16::MAX - 1,
"Attempted to immutably borrow cell while it was mutably borrowed.",
);
RwCellGuard {
value: &*(self.inner.value.get() as *const T),
borrow_state: &self.inner.borrow_state,
}
}
}
#[inline(always)]
pub fn borrow_mut(&self) -> RwCellGuardMut<'_,T> {
unsafe {
Self::abort_if(
self.inner.borrow_state.swap(u16::MAX, Ordering::AcqRel) != 0,
"Attempted to mutably borrow cell while other borrows already existed.",
);
RwCellGuardMut {
value: &mut *self.inner.value.get(),
borrow_state: &self.inner.borrow_state,
}
}
}
#[inline(always)]
pub fn free(&self) -> bool {
self.inner.borrow_state.load(Ordering::Acquire) == 0
}
#[inline(always)]
fn abort_if(condition: bool, reason: &str) {
if condition {
AbortPanic::abort(reason);
}
}
}
#[derive(Debug, Default)]
struct RwCellInner<T> {
value: UnsafeCell<T>,
borrow_state: AtomicU16,
}
#[derive(Debug)]
pub struct RwCellGuard<'a, T: ?Sized> {
value: &'a T,
borrow_state: &'a AtomicU16,
}
impl<'a, T: ?Sized> RwCellGuard<'a, T> {
#[inline(always)]
pub unsafe fn detach(self) -> RwCellGuard<'static, T> {
transmute(self)
}
#[inline(always)]
pub fn map<U, F>(orig: Self, f: F) -> RwCellGuard<'a, U>
where
F: FnOnce(&T) -> &U,
U: ?Sized,
{
let result = RwCellGuard {
value: f(orig.value),
borrow_state: orig.borrow_state,
};
forget(orig);
result
}
}
impl<'a, T: ?Sized> Deref for RwCellGuard<'a, T> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &Self::Target {
self.value
}
}
impl<'a, T: ?Sized> Drop for RwCellGuard<'a, T> {
#[inline(always)]
fn drop(&mut self) {
self.borrow_state.fetch_sub(1, Ordering::AcqRel);
}
}
#[derive(Debug)]
pub struct RwCellGuardMut<'a, T: ?Sized> {
value: &'a mut T,
borrow_state: &'a AtomicU16,
}
impl<'a, T: ?Sized> RwCellGuardMut<'a, T> {
#[inline(always)]
pub unsafe fn detach(self) -> RwCellGuardMut<'static, T> {
transmute(self)
}
#[inline(always)]
pub fn map<U, F>(orig: Self, f: F) -> RwCellGuardMut<'a, U>
where
F: FnOnce(&mut T) -> &mut U,
U: ?Sized,
{
let RwCellGuardMutDestructure {
value,
borrow_state,
} = orig.into();
RwCellGuardMut {
value: f(value),
borrow_state,
}
}
}
impl<'a, T: ?Sized> Deref for RwCellGuardMut<'a, T> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &Self::Target {
self.value
}
}
impl<'a, T: ?Sized> DerefMut for RwCellGuardMut<'a, T> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
self.value
}
}
impl<'a, T: ?Sized> Drop for RwCellGuardMut<'a, T> {
#[inline(always)]
fn drop(&mut self) {
self.borrow_state.store(0, Ordering::Release);
}
}
struct RwCellGuardMutDestructure<'a, T: ?Sized> {
value: &'a mut T,
borrow_state: &'a AtomicU16,
}
impl<'a, T: ?Sized> From<RwCellGuardMut<'a, T>> for RwCellGuardMutDestructure<'a, T> {
#[inline(always)]
fn from(value: RwCellGuardMut<'a, T>) -> Self {
unsafe {
let mut result = MaybeUninit::uninit();
(result.as_mut_ptr() as *mut RwCellGuardMut<T>).write(value);
result.assume_init()
}
}
}
struct AbortPanic(*const str);
impl AbortPanic {
#[allow(unused_variables)]
#[inline(always)]
fn abort(message: &str) -> ! {
let guard = Self(message);
panic!("{:?}", message);
}
}
impl Drop for AbortPanic {
fn drop(&mut self) {
unsafe {
panic!("{:?}", &*self.0);
}
}
}