[−][src]Struct crndm::prc::Prc
A single-thread reference-counting persistent pointer. 'Prc' stands for 'Persistent Reference Counted'.
The main aspect of Prc<T>
is that its counters are transactional which
means that functions pclone
, downgrade
, and upgrade
require a
Journal
to operate. In other words, you need to wrap them in a
transaction
.
Prc
uses reference counting to manage memory. Although it provides a fast
solution for deallocation without scan, cyclic references yield a memory
leak. At this point, we have not provided a static solution to detect cyclic
references. However, following Rust's partial solution for that, you may use
Weak
references for reference cycles.
References to data can be strong (using pclone
), weak (using downgrade
),
or volatile weak (using volatile
). The first two generate NV-to-NV
pointers, while the last on is a V-to-NV pointer. Please see Weak
and
VWeak
for more details on their implementation and safety.
Examples
use crndm::prc::Prc; use crndm::clone::PClone; P::transaction(|j| { let p = Prc::<i32,P>::new(1, j); // Create a new persistent strong reference let s = p.pclone(j); assert_eq!(*p, *s); assert_eq!(2, Prc::strong_count(&p)); assert_eq!(0, Prc::weak_count(&p)); // Create a new persistent weak reference let w = Prc::downgrade(&p, j); assert_eq!(2, Prc::strong_count(&p)); assert_eq!(1, Prc::weak_count(&p)); // Create a new volatile weak reference let v = Prc::volatile(&p); assert_eq!(2, Prc::strong_count(&p)); assert_eq!(1, Prc::weak_count(&p)); // Upgrade the persistent weak ref to a strong ref let ws = w.upgrade(j).unwrap(); assert_eq!(3, Prc::strong_count(&p)); assert_eq!(1, Prc::weak_count(&p)); // Upgrade the volatile weak ref to a strong ref let vs = w.upgrade(j).unwrap(); assert_eq!(4, Prc::strong_count(&p)); assert_eq!(1, Prc::weak_count(&p)); }).unwrap();
Implementations
impl<T: PSafe, A: MemPool> Prc<T, A>
[src]
pub fn new(value: T, journal: &Journal<A>) -> Prc<T, A>
[src]
Constructs a new Prc<T>
.
It also creates a DropOnFailure
log to make sure that if the program
crashes, the allocation drops of recovery.
Examples
use crndm::prc::Prc; P::transaction(|j| { let five = Prc::new(5, j); }).unwrap();
pub fn new_uninit(journal: &Journal<A>) -> Prc<MaybeUninit<T>, A>
[src]
Constructs a new Prc
with uninitialized contents.
A DropOnFailure
log is taken for the allocation.
Examples
use crndm::prc::Prc; P::transaction(|j| { let mut five = Prc::<u32,Heap>::new_uninit(j); let five = unsafe { // Deferred initialization: Prc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); five.assume_init() }; assert_eq!(*five, 5) }).unwrap();
pub fn new_zeroed(journal: &Journal<A>) -> Prc<MaybeUninit<T>, A>
[src]
Constructs a new Prc
with uninitialized contents, with the memory
being filled with 0
bytes.
See MaybeUninit::zeroed
for examples of correct and incorrect usage of
this method.
Examples
use crndm::prc::Prc; P::transaction(|j| { let zero = Prc::<i32,P>::new_zeroed(j); let zero = unsafe { zero.assume_init() }; assert_eq!(*zero, 0) }).unwrap();
pub fn from(p: Prc<T, A>) -> Self
[src]
Owns contents of p
without cloning, leaving p
untouched
impl<T: PSafe, A: MemPool> Prc<MaybeUninit<T>, A>
[src]
pub unsafe fn assume_init(self) -> Prc<T, A>
[src]
Converts to Rc<T>
.
Safety
As with MaybeUninit::assume_init
,
it is up to the caller to guarantee that the inner value
really is in an initialized state.
Calling this when the content is not yet fully initialized
causes immediate undefined behavior.
Examples
use crndm::prc::Prc; crndm::transaction(|j| { let mut five = Prc::<u32,P>::new_uninit(j); let five = unsafe { // Deferred initialization: Prc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); five.assume_init() }; assert_eq!(*five, 5); }).unwrap();
impl<T: PSafe, A: MemPool> Prc<MaybeUninit<T>, A>
[src]
pub fn get_mut(this: &mut Self) -> Option<&mut MaybeUninit<T>>
[src]
Returns a mutable reference into the given Prc
, if there are
no other Prc
or Weak
pointers to the same allocation.
Returns None
otherwise, because it is not safe to mutate a shared
value. It only works for Prc<MaybeUninit<T>>
to be able to defer the
initialization.
Examples
use crndm::prc::Prc; P::transaction(|j| { let mut five = Prc::<u32,P>::new_uninit(j); let five = unsafe { // Deferred initialization: Prc::get_mut(&mut five).unwrap().as_mut_ptr().write(5); five.assume_init() }; assert_eq!(*five, 5) }).unwrap();
pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut MaybeUninit<T>
[src]
Returns a mutable reference into the given Prc
,
without any check.
It only works for Prc<MaybeUninit<T>>
to be able to defer the
initialization.
Safety
Any other Prc
or Weak
pointers to the same allocation must not be
dereferenced for the duration of the returned borrow.
This is trivially the case if no such pointers exist,
for example immediately after Rc::new
.
Examples
use crndm::prc::Prc; P::transaction(|j| { let mut five = Prc::<i32,P>::new_uninit(j); let five = unsafe { // Deferred initialization: Prc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); five.assume_init() }; assert_eq!(*five, 5); }).unwrap();
impl<T: PSafe + ?Sized, A: MemPool> Prc<T, A>
[src]
pub fn downgrade(this: &Self, journal: &Journal<A>) -> Weak<T, A>
[src]
Creates a new Weak
pointer to this allocation.
Examples
use crndm::prc::Prc; P::transaction(|j| { let five = Prc::new(5, j); let _weak_five = Prc::downgrade(&five, j); }).unwrap()
pub fn volatile(this: &Self) -> VWeak<T, A>
[src]
Creates a new VWeak
pointer to this allocation.
pub fn weak_count(this: &Self) -> usize
[src]
Gets the number of Weak
pointers to this allocation.
Examples
use crndm::prc::Prc; P::transaction(|j| { let five = Prc::new(5, j); let _weak_five = Prc::downgrade(&five, j); assert_eq!(1, Prc::weak_count(&five)); }).unwrap()
pub fn strong_count(this: &Self) -> usize
[src]
Gets the number of Weak
pointers to this allocation.
Examples
use crndm::prc::Prc; use crndm::clone::PClone; P::transaction(|j| { let five = Prc::new(5, j); let _also_five = Prc::pclone(&five, j); assert_eq!(2, Prc::strong_count(&five)); }).unwrap();
pub fn ptr_eq(this: &Self, other: &Self) -> bool
[src]
Returns true
if the two Prc
s point to the same allocation
(in a vein similar to ptr::eq
).
Examples
use crndm::prc::Prc; use crndm::clone::PClone; P::transaction(|j| { let five = Prc::new(5, j); let same_five = Prc::pclone(&five, j); let other_five = Prc::new(5, j); assert!(Prc::ptr_eq(&five, &same_five)); assert!(!Prc::ptr_eq(&five, &other_five)); }).unwrap();
Trait Implementations
impl<T: PSafe + ?Sized, A: MemPool> AsRef<T> for Prc<T, A>
[src]
impl<T: PSafe + ?Sized, A: MemPool> Borrow<T> for Prc<T, A>
[src]
impl<T: Debug + PSafe + ?Sized, A: MemPool> Debug for Prc<T, A>
[src]
impl<T: PSafe + ?Sized, A: MemPool> Deref for Prc<T, A>
[src]
impl<T: Display + PSafe + ?Sized, A: MemPool> Display for Prc<T, A>
[src]
impl<T: PSafe + ?Sized, A: MemPool> Drop for Prc<T, A>
[src]
pub fn drop(&mut self)
[src]
Drops the Prc
safely
This will decrement the strong reference count. If the strong reference
count reaches zero then the only other references (if any) are
Weak
, so we drop
the inner value on commit using a DropOnCommit
log.
Examples
use crndm::prc::Prc; use crndm::clone::PClone; struct Foo; impl Drop for Foo { fn drop(&mut self) { println!("dropped!"); } } P::transaction(|j| { let foo = Prc::new(Foo, j); let foo2 = Prc::pclone(&foo, j); drop(foo); // Doesn't print anything drop(foo2); // Prints "dropped!" }).unwrap();
impl<T: Eq + PSafe + ?Sized, A: MemPool> Eq for Prc<T, A>
[src]
impl<T: Hash + PSafe + ?Sized, A: MemPool> Hash for Prc<T, A>
[src]
pub fn hash<H: Hasher>(&self, state: &mut H)
[src]
pub fn hash_slice<H>(data: &[Self], state: &mut H) where
H: Hasher,
1.3.0[src]
H: Hasher,
impl<T: Ord + PSafe + ?Sized, A: MemPool> Ord for Prc<T, A>
[src]
pub fn cmp(&self, other: &Prc<T, A>) -> Ordering
[src]
#[must_use]pub fn max(self, other: Self) -> Self
1.21.0[src]
#[must_use]pub fn min(self, other: Self) -> Self
1.21.0[src]
#[must_use]pub fn clamp(self, min: Self, max: Self) -> Self
1.50.0[src]
impl<T: PSafe + ?Sized, A: MemPool> PClone<A> for Prc<T, A>
[src]
pub fn pclone(&self, journal: &Journal<A>) -> Prc<T, A>
[src]
Creates a new strong reference to the object
It increments the strong reference counter in a failure-atomic manner. When a transaction is aborted or power fails, every strong references to the object should be gone, and the counters should rollback to the consistent state before the transaction.
Examples
let root = P::open::<Prc<i32>>("foo.pool", O_CF).unwrap(); let _ = P::transaction(|j| { let _n1 = root.pclone(j); let _n2 = root.pclone(j); let _n3 = root.pclone(j); assert_eq!(4, Prc::strong_count(&root)); panic!("abort") }); assert_eq!(1, Prc::strong_count(&root));
pub fn pclone_from(&mut self, source: &Self, journal: &Journal<A>)
[src]
impl<T: PartialEq + PSafe + ?Sized, A: MemPool> PartialEq<Prc<T, A>> for Prc<T, A>
[src]
pub fn eq(&self, other: &Prc<T, A>) -> bool
[src]
#[must_use]pub fn ne(&self, other: &Rhs) -> bool
1.0.0[src]
impl<T: PartialOrd + PSafe + ?Sized, A: MemPool> PartialOrd<Prc<T, A>> for Prc<T, A>
[src]
pub fn partial_cmp(&self, other: &Prc<T, A>) -> Option<Ordering>
[src]
pub fn lt(&self, other: &Prc<T, A>) -> bool
[src]
pub fn le(&self, other: &Prc<T, A>) -> bool
[src]
pub fn gt(&self, other: &Prc<T, A>) -> bool
[src]
pub fn ge(&self, other: &Prc<T, A>) -> bool
[src]
impl<T: PSafe, A: MemPool> PmemUsage for Prc<T, A>
[src]
impl<T: PSafe + PmemUsage + ?Sized, A: MemPool> PmemUsage for Prc<T, A>
[src]
impl<T: PSafe + ?Sized, A: MemPool> Pointer for Prc<T, A>
[src]
impl<T: RootObj<A> + PSafe, A: MemPool> RootObj<A> for Prc<T, A>
[src]
impl<T: Default + PSafe + ?Sized, A: MemPool> RootObj<A> for Prc<T, A>
[src]
impl<T: ?Sized, A: MemPool> !Send for Prc<T, A>
[src]
impl<T: ?Sized, A: MemPool> !Sync for Prc<T, A>
[src]
impl<T: ?Sized, A: MemPool> !TxOutSafe for Prc<T, A>
[src]
impl<T: PSafe + ?Sized, A: MemPool> Unpin for Prc<T, A>
[src]
impl<T: ?Sized, A: MemPool> !VSafe for Prc<T, A>
[src]
Auto Trait Implementations
impl<T: ?Sized, A> LooseTxInUnsafe for Prc<T, A> where
A: LooseTxInUnsafe,
T: LooseTxInUnsafe,
[src]
A: LooseTxInUnsafe,
T: LooseTxInUnsafe,
impl<T: ?Sized, A> PSafe for Prc<T, A>
[src]
impl<T: ?Sized, A> RefUnwindSafe for Prc<T, A> where
A: RefUnwindSafe,
T: RefUnwindSafe,
[src]
A: RefUnwindSafe,
T: RefUnwindSafe,
impl<T: ?Sized, A> TxInSafe for Prc<T, A> where
A: TxInSafe,
T: TxInSafe,
[src]
A: TxInSafe,
T: TxInSafe,
impl<T: ?Sized, A> UnwindSafe for Prc<T, A> where
A: UnwindSafe,
T: UnwindSafe,
[src]
A: UnwindSafe,
T: UnwindSafe,
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
pub fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T> ToString for T where
T: Display + ?Sized,
[src]
T: Display + ?Sized,
impl<T, A> ToString<A> for T where
A: MemPool,
T: Display + ?Sized,
[src]
A: MemPool,
T: Display + ?Sized,
pub default fn to_pstring(&Self, &Journal<A>) -> String<A>
[src]
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
pub fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,
type Error = <U as TryFrom<T>>::Error
The type returned in the event of a conversion error.
pub fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>
[src]
impl<V, T> VZip<V> for T where
V: MultiLane<T>,
V: MultiLane<T>,