use crate::alloc::MemPool;
use crate::cell::RootObj;
use crate::clone::*;
use crate::ptr::Ptr;
use crate::stm::*;
use crate::{PSafe, VSafe, TxOutSafe};
use std::cmp::Ordering;
use std::convert::From;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::marker::Unpin;
use std::mem;
use std::ops::{Deref,DerefMut};
use std::pin::Pin;
use std::ptr::{self, NonNull};
pub struct Pbox<T: PSafe + ?Sized, A: MemPool>(Ptr<T, A>, u8);
impl<T: ?Sized, A: MemPool> !TxOutSafe for Pbox<T, A> {}
impl<A: MemPool, T: ?Sized> !Send for Pbox<T, A> {}
impl<A: MemPool, T: ?Sized> !VSafe for Pbox<T, A> {}
impl<T: PSafe, A: MemPool> Pbox<T, A> {
pub fn new(x: T, journal: &Journal<A>) -> Pbox<T, A> {
if mem::size_of::<T>() == 0 {
Pbox(Ptr::dangling(), 0)
} else {
unsafe {
let p = A::new(x, journal);
Pbox(Ptr::from_mut(p), 0)
}
}
}
pub fn off(&self) -> u64 {
self.0.off()
}
pub fn new_uninit(journal: &Journal<A>) -> Pbox<mem::MaybeUninit<T>, A> {
let p = unsafe { A::new_uninit::<mem::MaybeUninit<T>>(journal) };
Pbox(Ptr::from_mut(p), 0)
}
pub fn new_zeroed(journal: &Journal<A>) -> Pbox<mem::MaybeUninit<T>, A> {
unsafe {
let mut uninit = Self::new_uninit(journal);
ptr::write_bytes::<T>(uninit.as_mut().as_mut_ptr(), 0, 1);
uninit
}
}
#[inline(always)]
pub fn pin(x: T, journal: &Journal<A>) -> Pin<Pbox<T, A>> {
Self::new(x, journal).into()
}
}
impl<T: PSafe, A: MemPool> Pbox<mem::MaybeUninit<T>, A> {
#[inline]
pub unsafe fn assume_init(self) -> Pbox<T, A> {
Pbox::from_raw(Pbox::into_raw(self) as *mut T)
}
}
impl<T: PSafe, A: MemPool> Pbox<T, A> {
pub fn initialize(boxed: &Option<Pbox<T, A>>, value: T) -> crate::result::Result<()> {
assert!(
!Journal::<A>::is_running(),
"Pbox::initialize() cannot be used inside a transaction"
);
match boxed {
Some(_) => Err("already initialized".to_string()),
None => if A::valid(boxed) {
unsafe {
let new = A::atomic_new(value);
let bnew = Some(Pbox::<T, A>::from_raw(new.0));
let src = crate::utils::as_slice64(&bnew);
let mut base = A::off_unchecked(boxed);
for i in src {
A::log64(base, *i, new.3);
base += 8;
}
A::perform(new.3);
}
Ok(())
} else {
Err("The object is not in the PM".to_string())
}
}
}
}
impl<T: PSafe + ?Sized, A: MemPool> Pbox<T, A> {
#[inline]
pub unsafe fn from_raw(raw: *mut T) -> Self {
Pbox(Ptr::new_unchecked(raw), 0)
}
#[inline]
pub fn into_raw(b: Pbox<T, A>) -> *mut T {
Pbox::into_raw_non_null(b).as_ptr()
}
#[inline]
pub fn into_raw_non_null(b: Pbox<T, A>) -> NonNull<T> {
unsafe { NonNull::new_unchecked(Pbox::into_unique(b).as_mut_ptr()) }
}
#[inline]
#[doc(hidden)]
pub(crate) fn into_unique(b: Pbox<T, A>) -> Ptr<T, A> {
let unique = b.0.clone();
mem::forget(b);
unsafe { Ptr::new_unchecked(unique.get_mut() as *mut T) }
}
#[inline]
pub unsafe fn leak<'a>(b: Pbox<T, A>) -> &'a mut T
where
T: 'a, {
&mut *Pbox::into_raw(b)
}
pub fn into_pin(boxed: Pbox<T, A>) -> Pin<Pbox<T, A>>
where
T: Sized,
{
unsafe { Pin::new_unchecked(boxed) }
}
pub unsafe fn as_mut(&mut self) -> &mut T {
self.0.as_mut()
}
fn get_ref(&self) -> &T {
self.0.as_ref()
}
}
unsafe impl<#[may_dangle] T: PSafe + ?Sized, A: MemPool> Drop for Pbox<T, A> {
fn drop(&mut self) {
unsafe {
if !self.0.is_dangling() {
let p = self.0.as_mut();
std::ptr::drop_in_place(p);
A::free(p);
}
}
}
}
impl<T: RootObj<A> + PSafe, A: MemPool> RootObj<A> for Pbox<T, A> {
#[inline]
default fn init(journal: &Journal<A>) -> Pbox<T, A> {
Pbox::new(T::init(journal), journal)
}
}
impl<T: PSafe + PClone<A> + ?Sized, A: MemPool> PClone<A> for Pbox<T, A> {
#[inline]
default fn pclone(&self, journal: &Journal<A>) -> Pbox<T, A> {
Pbox::new((**self).pclone(journal), journal)
}
}
impl<T: PSafe + PartialEq + ?Sized, A: MemPool> PartialEq for Pbox<T, A> {
#[inline]
fn eq(&self, other: &Pbox<T, A>) -> bool {
PartialEq::eq(&**self, &**other)
}
#[inline]
fn ne(&self, other: &Pbox<T, A>) -> bool {
PartialEq::ne(&**self, &**other)
}
}
impl<T: PSafe + PartialOrd + ?Sized, A: MemPool> PartialOrd for Pbox<T, A> {
#[inline]
fn partial_cmp(&self, other: &Pbox<T, A>) -> Option<Ordering> {
PartialOrd::partial_cmp(&**self, &**other)
}
#[inline]
fn lt(&self, other: &Pbox<T, A>) -> bool {
PartialOrd::lt(&**self, &**other)
}
#[inline]
fn le(&self, other: &Pbox<T, A>) -> bool {
PartialOrd::le(&**self, &**other)
}
#[inline]
fn ge(&self, other: &Pbox<T, A>) -> bool {
PartialOrd::ge(&**self, &**other)
}
#[inline]
fn gt(&self, other: &Pbox<T, A>) -> bool {
PartialOrd::gt(&**self, &**other)
}
}
impl<T: PSafe + Ord + ?Sized, A: MemPool> Ord for Pbox<T, A> {
#[inline]
fn cmp(&self, other: &Pbox<T, A>) -> Ordering {
Ord::cmp(&**self, &**other)
}
}
impl<T: PSafe + Eq + ?Sized, A: MemPool> Eq for Pbox<T, A> {}
impl<T: PSafe + Hash + ?Sized, A: MemPool> Hash for Pbox<T, A> {
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state);
}
}
impl<T: PSafe + Hasher + ?Sized, A: MemPool> Hasher for Pbox<T, A> {
fn finish(&self) -> u64 {
(**self).finish()
}
fn write(&mut self, bytes: &[u8]) {
unsafe { self.as_mut().write(bytes) }
}
fn write_u8(&mut self, i: u8) {
unsafe { self.as_mut().write_u8(i) }
}
fn write_u16(&mut self, i: u16) {
unsafe { self.as_mut().write_u16(i) }
}
fn write_u32(&mut self, i: u32) {
unsafe { self.as_mut().write_u32(i) }
}
fn write_u64(&mut self, i: u64) {
unsafe { self.as_mut().write_u64(i) }
}
fn write_u128(&mut self, i: u128) {
unsafe { self.as_mut().write_u128(i) }
}
fn write_usize(&mut self, i: usize) {
unsafe { self.as_mut().write_usize(i) }
}
fn write_i8(&mut self, i: i8) {
unsafe { self.as_mut().write_i8(i) }
}
fn write_i16(&mut self, i: i16) {
unsafe { self.as_mut().write_i16(i) }
}
fn write_i32(&mut self, i: i32) {
unsafe { self.as_mut().write_i32(i) }
}
fn write_i64(&mut self, i: i64) {
unsafe { self.as_mut().write_i64(i) }
}
fn write_i128(&mut self, i: i128) {
unsafe { self.as_mut().write_i128(i) }
}
fn write_isize(&mut self, i: isize) {
unsafe { self.as_mut().write_isize(i) }
}
}
impl<T: PSafe, A: MemPool> From<Pbox<T, A>> for Pin<Pbox<T, A>> {
fn from(boxed: Pbox<T, A>) -> Self {
Pbox::into_pin(boxed)
}
}
impl<T: PSafe + fmt::Display + ?Sized, A: MemPool> fmt::Display for Pbox<T, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
impl<T: PSafe + fmt::Debug + ?Sized, A: MemPool> fmt::Debug for Pbox<T, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl<T: PSafe + ?Sized, A: MemPool> Deref for Pbox<T, A> {
type Target = T;
fn deref(&self) -> &T {
self.0.as_ref()
}
}
impl<T: PSafe, A: MemPool> DerefMut for Pbox<T, A> {
#[track_caller]
fn deref_mut(&mut self) -> &mut T {
let d = self.0.as_mut();
if self.1 == 0 && A::valid(&self.1) {
let journal = Journal::<A>::try_current()
.expect("Unrecoverable data modification").0;
unsafe {
d.create_log(&*journal, Notifier::NonAtomic(Ptr::from_ref(&self.1)));
}
}
d
}
}
impl<T: PSafe + ?Sized, A: MemPool> AsRef<T> for Pbox<T, A> {
fn as_ref(&self) -> &T {
self.get_ref()
}
}
impl<T: PSafe + ?Sized, A: MemPool> Unpin for Pbox<T, A> {}