[][src]Struct crndm::prc::Prc

pub struct Prc<T: PSafe + ?Sized, A: MemPool> { /* fields omitted */ }

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 Prcs 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]

type Target = T

The resulting type after dereferencing.

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]

impl<T: Ord + PSafe + ?Sized, A: MemPool> Ord for Prc<T, A>[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));

impl<T: PartialEq + PSafe + ?Sized, A: MemPool> PartialEq<Prc<T, A>> for Prc<T, A>[src]

impl<T: PartialOrd + PSafe + ?Sized, A: MemPool> PartialOrd<Prc<T, A>> for Prc<T, A>[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]

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]

impl<T: ?Sized, A> TxInSafe for Prc<T, A> where
    A: TxInSafe,
    T: TxInSafe
[src]

impl<T: ?Sized, A> UnwindSafe for Prc<T, A> where
    A: UnwindSafe,
    T: UnwindSafe
[src]

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, A> ToString<A> for T where
    A: MemPool,
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

impl<V, T> VZip<V> for T where
    V: MultiLane<T>,