use crate::ptr::{LogNonNull,NonNull};
use crate::convert::PFrom;
use crate::alloc::MemPool;
use crate::stm::Journal;
use crate::*;
use std::cell::UnsafeCell;
use std::fmt::{self, Debug, Display};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::panic::{RefUnwindSafe, UnwindSafe};
#[cfg(any(feature = "use_pspd", feature = "use_vspd"))]
use crate::cell::TCell;
#[cfg(not(feature = "no_dyn_borrow_checking"))]
use crate::cell::VCell;
pub struct PRefCell<T: PSafe + ?Sized, A: MemPool> {
heap: PhantomData<A>,
#[cfg(not(feature = "no_dyn_borrow_checking"))]
borrow: VCell<i8, A>,
#[cfg(any(feature = "use_pspd", feature = "use_vspd"))]
temp: TCell<Option<*mut T>, A>,
#[cfg(any(feature = "use_pspd", feature = "use_vspd"))]
value: UnsafeCell<T>,
#[cfg(not(any(feature = "use_pspd", feature = "use_vspd")))]
value: UnsafeCell<(u8, T)>,
}
impl<T: PSafe + ?Sized, A: MemPool> RefUnwindSafe for PRefCell<T, A> {}
impl<T: PSafe + ?Sized, A: MemPool> UnwindSafe for PRefCell<T, A> {}
unsafe impl<T: PSafe + ?Sized, A: MemPool> TxInSafe for PRefCell<T, A> {}
impl<T: ?Sized, A: MemPool> !TxOutSafe for PRefCell<T, A> {}
unsafe impl<T: PSafe + ?Sized, A: MemPool> PSafe for PRefCell<T, A> {}
unsafe impl<T: PSafe + ?Sized, A: MemPool> Send for PRefCell<T, A> {}
impl<T: ?Sized, A: MemPool> !Sync for PRefCell<T, A> {}
impl<T: ?Sized, A: MemPool> !PSend for PRefCell<T, A> {}
impl<T: PSafe, A: MemPool> PRefCell<T, A> {
pub fn new(value: T) -> Self {
Self::def(value)
}
#[inline]
fn def(value: T) -> Self {
PRefCell {
heap: PhantomData,
#[cfg(not(feature = "no_dyn_borrow_checking"))]
borrow: VCell::new(0),
#[cfg(any(feature = "use_pspd", feature = "use_vspd"))]
temp: TCell::new_invalid(None),
#[cfg(any(feature = "use_pspd", feature = "use_vspd"))]
value: UnsafeCell::new(value),
#[cfg(not(any(feature = "use_pspd", feature = "use_vspd")))]
value: UnsafeCell::new((0, value)),
}
}
#[inline]
pub fn replace(&self, t: T, j: &Journal<A>) -> T {
std::mem::replace(&mut *self.borrow_mut(j), t)
}
#[inline]
pub fn replace_with<F: FnOnce(&mut T) -> T>(&self, j: &Journal<A>, f: F) -> T {
let mut_borrow = &mut *self.borrow_mut(j);
let replacement = f(mut_borrow);
std::mem::replace(mut_borrow, replacement)
}
#[inline]
pub fn swap(&self, other: &Self, j: &Journal<A>) {
std::mem::swap(&mut *self.borrow_mut(j), &mut *other.borrow_mut(j))
}
}
impl<T: PSafe + RootObj<A>, A: MemPool> RootObj<A> for PRefCell<T, A> {
default fn init(j: &Journal<A>) -> Self {
Self::def(T::init(j))
}
}
impl<T: PSafe + Display + ?Sized, A: MemPool> Display for PRefCell<T, A> {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
self.as_ref().fmt(fmt)
}
}
impl<T: PSafe + Debug + ?Sized, A: MemPool> Debug for PRefCell<T, A> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
self.as_ref().fmt(f)
}
}
impl<T: PSafe + ?Sized, A: MemPool> PRefCell<T, A> {
#[inline(always)]
#[allow(clippy::mut_from_ref)]
fn self_mut(&self) -> &mut Self {
unsafe {
let ptr: *const Self = self;
&mut *(ptr as *mut Self)
}
}
#[inline]
#[allow(clippy::mut_from_ref)]
pub fn get_mut(&mut self, journal: &Journal<A>) -> &mut T {
let inner = unsafe { &mut *self.value.get() };
self.create_log(journal);
#[cfg(any(feature = "use_pspd", feature = "use_vspd"))] unsafe {
if let Some(tmp) = *self.temp {
&mut *tmp
} else {
&mut *inner
}
}
#[cfg(not(any(feature = "use_pspd", feature = "use_vspd")))] {
&mut inner.1
}
}
#[inline]
pub unsafe fn as_mut(&self) -> &mut T {
#[cfg(any(feature = "use_pspd", feature = "use_vspd"))] {
if let Some(tmp) = *self.temp {
&mut *tmp
} else {
&mut *self.value.get()
}
}
#[cfg(not(any(feature = "use_pspd", feature = "use_vspd")))] {
&mut (*self.value.get()).1
}
}
#[inline]
pub fn as_ref(&self) -> &T {
unsafe {
#[cfg(any(feature = "use_pspd", feature = "use_vspd"))] {
if let Some(tmp) = *self.temp {
&*tmp
} else {
&*self.value.get()
}
}
#[cfg(not(any(feature = "use_pspd", feature = "use_vspd")))] {
&(*self.value.get()).1
}
}
}
#[inline]
#[track_caller]
pub fn borrow(&self) -> Ref<'_, T, A> {
#[cfg(not(feature = "no_dyn_borrow_checking"))] {
let borrow = self.borrow.as_mut();
assert!(*borrow <= 0, "Value was already mutably borrowed ({})", *borrow);
*borrow = -1;
}
Ref { value: self, phantom: PhantomData }
}
#[inline]
pub fn read(&self) -> T
where
T: std::clone::Clone,
{
self.as_ref().clone()
}
#[inline]
#[track_caller]
pub(crate) fn create_log(&self, journal: &Journal<A>) {
unsafe {
let inner = &mut *self.value.get();
#[cfg(any(feature = "use_pspd", feature = "use_vspd"))] {
if self.temp.is_none() {
if self.temp.is_none() {
if let Some(p) = journal.draft(inner) {
self.temp.as_mut().replace(p);
}
}
}
}
#[cfg(not(any(feature = "use_pspd", feature = "use_vspd")))] {
use crate::ptr::Ptr;
use crate::stm::{Notifier, Logger};
if inner.0 == 0 {
assert!(A::valid(inner), "The object is not in the pool's valid range");
inner.1.create_log(journal, Notifier::NonAtomic(Ptr::from_ref(&inner.0)));
}
}
}
}
}
impl<T: PSafe + PClone<A>, A: MemPool> PFrom<Ref<'_, T, A>, A> for PRefCell<T, A> {
fn pfrom(other: Ref<'_, T, A>, j: &Journal<A>) -> Self {
Self::def(other.pclone(j))
}
}
impl<T: PSafe + PClone<A>, A: MemPool> PFrom<RefMut<'_, T, A>, A> for PRefCell<T, A> {
fn pfrom(other: RefMut<'_, T, A>, j: &Journal<A>) -> Self {
Self::def(other.pclone(j))
}
}
impl<T: PSafe, A: MemPool> PFrom<T, A> for PRefCell<T, A> {
fn pfrom(value: T, _j: &Journal<A>) -> Self {
Self::new(value)
}
}
impl<T: PSafe, A: MemPool> From<T> for PRefCell<T, A> {
fn from(value: T) -> Self {
Self::new(value)
}
}
impl<T: PSafe + Default, A: MemPool> PRefCell<T, A> {
pub fn take(&self, journal: &Journal<A>) -> T {
self.replace(Default::default(), journal)
}
}
impl<T: PSafe, A: MemPool> PRefCell<T, A> {
#[inline]
#[track_caller]
pub fn borrow_mut(&self, journal: &Journal<A>) -> RefMut<'_, T, A> {
#[cfg(not(feature = "no_dyn_borrow_checking"))] {
let borrow = self.borrow.as_mut();
assert!(*borrow >= 0, "Value was already immutably borrowed ({})", *borrow);
assert!(*borrow == 0, "Value was already mutably borrowed ({})", *borrow);
*borrow = 1;
}
RefMut {
value: unsafe { &mut *(self as *const Self as *mut Self) },
journal,
phantom: PhantomData
}
}
pub unsafe fn as_non_null_mut(&self, journal: &Journal<A>) -> LogNonNull<T, A> {
let inner = &mut *self.value.get();
#[cfg(any(feature = "use_pspd", feature = "use_vspd"))] {
LogNonNull::new_unchecked(inner, journal)
}
#[cfg(not(any(feature = "use_pspd", feature = "use_vspd")))] {
LogNonNull::new_unchecked(&mut inner.1, &mut inner.0, journal)
}
}
pub fn as_non_null(&self) -> NonNull<T> {
unsafe {
let inner = &mut *self.value.get();
#[cfg(any(feature = "use_pspd", feature = "use_vspd"))] {
NonNull::new_unchecked(inner)
}
#[cfg(not(any(feature = "use_pspd", feature = "use_vspd")))] {
NonNull::new_unchecked(&mut inner.1)
}
}
}
}
use crate::clone::PClone;
impl<T: PSafe + PClone<A>, A: MemPool> PClone<A> for PRefCell<T, A> {
#[inline]
fn pclone(&self, j: &Journal<A>) -> PRefCell<T, A> {
PRefCell::new(self.as_ref().pclone(j))
}
}
impl<T: PSafe + Clone, A: MemPool> Clone for PRefCell<T, A> {
#[inline]
fn clone(&self) -> PRefCell<T, A> {
PRefCell::new(self.as_ref().clone())
}
}
impl<T: PSafe + PartialEq + ?Sized, A: MemPool> PartialEq for PRefCell<T, A> {
#[inline]
fn eq(&self, other: &PRefCell<T, A>) -> bool {
*self.as_ref() == *other.as_ref()
}
}
impl<T: PSafe + Eq + ?Sized, A: MemPool> Eq for PRefCell<T, A> {}
impl<T: PSafe + PartialOrd + ?Sized, A: MemPool> PartialOrd for PRefCell<T, A> {
#[inline]
fn partial_cmp(&self, other: &PRefCell<T, A>) -> Option<std::cmp::Ordering> {
self.as_ref().partial_cmp(&*other.as_ref())
}
#[inline]
fn lt(&self, other: &PRefCell<T, A>) -> bool {
*self.as_ref() < *other.as_ref()
}
#[inline]
fn le(&self, other: &PRefCell<T, A>) -> bool {
*self.as_ref() <= *other.as_ref()
}
#[inline]
fn gt(&self, other: &PRefCell<T, A>) -> bool {
*self.as_ref() > *other.as_ref()
}
#[inline]
fn ge(&self, other: &PRefCell<T, A>) -> bool {
*self.as_ref() >= *other.as_ref()
}
}
impl<T: PSafe + Ord + ?Sized, A: MemPool> Ord for PRefCell<T, A> {
#[inline]
fn cmp(&self, other: &PRefCell<T, A>) -> std::cmp::Ordering {
self.as_ref().cmp(&*other.as_ref())
}
}
pub struct Ref<'b, T: 'b + PSafe + ?Sized, A: MemPool> {
value: *const PRefCell<T, A>,
phantom: PhantomData<&'b T>
}
impl<T: ?Sized, A: MemPool> !TxOutSafe for Ref<'_, T, A> {}
impl<T: ?Sized, A: MemPool> !Send for Ref<'_, T, A> {}
impl<T: ?Sized, A: MemPool> !Sync for Ref<'_, T, A> {}
impl<'b, T: PSafe + ?Sized, A: MemPool> Ref<'b, T, A> {
#[inline]
#[track_caller]
pub fn clone(orig: &Ref<'b, T, A>) -> Ref<'b, T, A> {
#[cfg(not(feature = "no_dyn_borrow_checking"))] {
let borrow = unsafe {(*orig.value).borrow.as_mut()};
assert!(*borrow > i8::MIN);
*borrow -= 1;
}
Ref { value: orig.value, phantom: PhantomData }
}
pub fn leak(orig: Ref<'b, T, A>) -> &'b T {
unsafe {(*orig.value).as_ref()}
}
}
#[cfg(feature = "refcell_lifetime_change")]
impl<T: PSafe + ?Sized, A: MemPool> Ref<'_, T, A> {
pub fn own<'a, 'b>(orig: Ref<'a, T, A>) -> Ref<'b, T, A> {
let res = Ref {
value: orig.value,
phantom: PhantomData
};
std::mem::forget(orig);
res
}
pub fn into_inner<'a>(orig: Ref<'a, T, A>) -> &'a PRefCell<T, A> {
let inner = orig.value;
std::mem::drop(orig);
unsafe { &*inner }
}
}
impl<T: PSafe + ?Sized, A: MemPool> Deref for Ref<'_, T, A> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe {(*self.value).as_ref()}
}
}
impl<T: fmt::Display + PSafe, A: MemPool> fmt::Display for Ref<'_, T, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
unsafe {(*self.value).fmt(f)}
}
}
impl<T: PSafe + ?Sized, A: MemPool> Drop for Ref<'_, T, A> {
fn drop(&mut self) {
#[cfg(not(feature = "no_dyn_borrow_checking"))] {
let borrow = unsafe {(*self.value).borrow.as_mut()};
*borrow += 1;
}
}
}
pub struct RefMut<'b, T: 'b + PSafe + ?Sized, A: MemPool> {
value: *mut PRefCell<T, A>,
journal: *const Journal<A>,
phantom: PhantomData<&'b T>
}
impl<T: ?Sized, A: MemPool> !TxOutSafe for RefMut<'_, T, A> {}
impl<T: ?Sized, A: MemPool> !Send for RefMut<'_, T, A> {}
impl<T: ?Sized, A: MemPool> !Sync for RefMut<'_, T, A> {}
#[cfg(feature = "refcell_lifetime_change")]
impl<T: PSafe + ?Sized, A: MemPool> RefMut<'_, T, A> {
pub fn own<'a, 'b>(orig: RefMut<'a, T, A>) -> RefMut<'b, T, A> {
let res = RefMut {
value: orig.value,
journal: orig.journal,
phantom: PhantomData
};
std::mem::forget(orig);
res
}
pub fn into_inner<'a>(orig: RefMut<'a, T, A>) -> &'a PRefCell<T, A> {
let inner = orig.value;
std::mem::drop(orig);
unsafe { &*inner }
}
}
impl<T: PSafe + ?Sized, A: MemPool> RefMut<'_, T, A> {
pub fn into_mut<'a>(r: RefMut<'a, T, A>) -> &'a mut T {
unsafe { (*r.value).as_mut() }
}
}
impl<T: PSafe + ?Sized, A: MemPool> Deref for RefMut<'_, T, A> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { (*self.value).as_ref() }
}
}
impl<T: PSafe + ?Sized, A: MemPool> DerefMut for RefMut<'_, T, A> {
#[inline]
#[track_caller]
fn deref_mut(&mut self) -> &mut T {
unsafe { (*self.value).get_mut(&*self.journal) }
}
}
impl<T: fmt::Display + PSafe + ?Sized, A: MemPool> fmt::Display for RefMut<'_, T, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
unsafe { (*self.value).fmt(f) }
}
}
impl<T: fmt::Debug + PSafe + ?Sized, A: MemPool> fmt::Debug for RefMut<'_, T, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
unsafe { (*self.value).fmt(f) }
}
}
impl<T: PSafe + ?Sized, A: MemPool> Drop for RefMut<'_, T, A> {
fn drop(&mut self) {
#[cfg(not(feature = "no_dyn_borrow_checking"))] unsafe {
let borrow = (*self.value).borrow.as_mut();
*borrow -= 1;
}
}
}