pub struct Pbox<T: PSafe + ?Sized, A: MemPool>(_, _);
Expand description

A pointer type for persistent heap allocation.

If Pbox is mutable, the underlying data can mutate after taking a log. It is necessary because compound types containing a Pbox may provide interior mutability (via PCell or PRefCell) though which the Pbox become mutably available. The log taken for interior mutability works only on the pointer value and does not include the referent object. Therefore, Pbox provides a logging mechanism to provide mutable dereferencing.

Examples

Create a boxed object in the persistent memory

use corundum::default::*;

type P = Allocator;

let _p = P::open_no_root("foo.pool", O_CF).unwrap();
 
transaction(|j| {
    let five = Pbox::new(5, j);
    assert_eq!(*five, 5);
}).unwrap();

Examples

Move a value from the stack to the persistent memory by creating a Pbox:

transaction(|j| {
    let val: u8 = 5;
    let boxed: Pbox<u8> = Pbox::new(val, j);
}).unwrap();

Move a value from a Pbox back to the stack by dereferencing:

transaction(|j| {
    let boxed: Pbox<u8> = Pbox::new(5, j);
    let val: u8 = *boxed;
}).unwrap();

Creating a recursive data structure:

#[derive(Debug)]
enum List<T: PSafe> {
    Cons(T, Pbox<List<T>>),
    Nil,
}

transaction(|j| {
    let list: List<i32> = List::Cons(1, Pbox::new(List::Cons(2, Pbox::new(List::Nil, j)), j));
    println!("{:?}", list);
}).unwrap();

This will print Cons(1, Cons(2, Nil)).

Recursive structures must be boxed, because if the definition of Cons looked like this:

Cons(T, List<T>),

It wouldn’t work. This is because the size of a List depends on how many elements are in the list, and so we don’t know how much memory to allocate for a Cons. By introducing a Pbox<T>, which has a defined size, we know how big Cons needs to be.

Implementations

Allocates memory on the persistent heap and then places x into it.

This doesn’t actually allocate if T is zero-sized.

Examples
Heap::transaction(|j| {
    let five = Pbox::new(5, j);
}).unwrap();

Constructs a new Pbox with uninitialized contents.

Examples
P::transaction(|j| {
    let mut five = Pbox::<u32>::new_uninit(j);
     
    let five = unsafe {
        // Deferred initialization:
        five.as_mut_ptr().write(5);
     
        five.assume_init()
    };
     
    assert_eq!(*five, 5)
}).unwrap()

Constructs a new Pbox 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
P::transaction(|j| {
    let zero = Pbox::<u32>::new_zeroed(j);
    let zero = unsafe { zero.assume_init() };

    assert_eq!(*zero, 0)
}).unwrap()

Constructs a new Pin<Pbox<T, A>>. If T does not implement Unpin, then x will be pinned in memory and unable to be moved.

Converts to Pbox<T, A>.

Safety

As with MaybeUninit::assume_init, it is up to the caller to guarantee that the value really is in an initialized state. Calling this when the content is not yet fully initialized causes immediate undefined behavior.

Initializes boxed data with value in-place if it is None

This function should not be called from a transaction as it updates data without taking high-level logs. If transaction is unsuccessful, there is no way to recover data. However, it is safe to use it outside a transaction because it uses low-level logs to provide safety for a single update without drop. A dynamic check at the beginning makes sure of that.

Examples
use corundum::default::*;
 
type P = Allocator;

let root = P::open::<Option<Pbox<i32>>>("foo.pool", O_CF).unwrap();

Pbox::initialize(&*root, 25);
 
let value = **root.as_ref().unwrap();
assert_eq!(value, 25);

Constructs a box from a raw pointer.

After calling this function, the raw pointer is owned by the resulting Pbox. Specifically, the Pbox destructor will call the destructor of T and free the allocated memory. For this to be safe, the memory must have been allocated in accordance with the memory layout used by Pbox .

Safety

This function is unsafe because improper use may lead to memory problems. For example, a double-free may occur if the function is called twice on the same raw pointer.

Consumes the Pbox, returning a wrapped raw pointer.

The pointer will be properly aligned and non-null.

After calling this function, the caller is responsible for the memory previously managed by the Pbox. In particular, the caller should properly destroy T and release the memory, taking into account the [memory layout] used by Pbox. The easiest way to do this is to convert the raw pointer back into a Pbox with the Pbox::from_raw function, allowing the Pbox destructor to perform the cleanup.

Note: this is an associated function, which means that you have to call it as Pbox::into_raw(b) instead of b.into_raw(). This is so that there is no conflict with a method on the inner type.

Consumes the Pbox, returning the wrapped pointer as NonNull<T>.

After calling this function, the caller is responsible for the memory previously managed by the Pbox. In particular, the caller should properly destroy T and release the memory. The easiest way to do so is to convert the NonNull<T> pointer into a raw pointer and back into a Pbox with the Pbox::from_raw function.

Note: this is an associated function, which means that you have to call it as Pbox::into_raw_non_null(b) instead of b.into_raw_non_null(). This is so that there is no conflict with a method on the inner type.

Consumes and leaks the Pbox, returning a mutable reference, &'a mut T. Note that the type T must outlive the chosen lifetime 'a. If the type has only static references, or none at all, then this may be chosen to be 'static.

This function is mainly useful for data that lives for the remainder of the program’s life. Dropping the returned reference will cause a memory leak. If this is not acceptable, the reference should first be wrapped with the Pbox::from_raw function producing a Pbox. This Pbox can then be dropped which will properly destroy T and release the allocated memory.

Note: this is an associated function, which means that you have to call it as Pbox::leak(b) instead of b.leak(). This is so that there is no conflict with a method on the inner type.

Safety

This function is considered unsafe in persistent memory programming because memory leak is permanent and undesirable.

Examples

Simple usage:

Heap::transaction(|j| unsafe {
    let x = Pbox::new(41, j);
    let static_ref: &'static mut usize = Pbox::leak(x);
    *static_ref += 1;
    assert_eq!(*static_ref, 42);
}).unwrap();

Converts a Pbox<T, A> into a Pin<Pbox<T, A>>

This conversion does not allocate on the heap and happens in place.

This is also available via From.

Trait Implementations

Converts this type into a shared reference of the (usually inferred) input type.

Formats the value using the given formatter. Read more

The resulting type after dereferencing.

Dereferences the value.

Mutably dereferences the value.

Formats the value using the given formatter. Read more

Executes the destructor for this type. Read more

Converts a Pbox<T, A> into a Pin<Pbox<T, A>>

This conversion does not allocate on the heap and happens in place.

Feeds this value into the given Hasher. Read more

Feeds a slice of this type into the given Hasher. Read more

Returns the hash value for the values written so far. Read more

Writes some data into this Hasher. Read more

Writes a single u8 into this hasher.

Writes a single u16 into this hasher.

Writes a single u32 into this hasher.

Writes a single u64 into this hasher.

Writes a single u128 into this hasher.

Writes a single usize into this hasher.

Writes a single i8 into this hasher.

Writes a single i16 into this hasher.

Writes a single i32 into this hasher.

Writes a single i64 into this hasher.

Writes a single i128 into this hasher.

Writes a single isize into this hasher.

This method returns an Ordering between self and other. Read more

Compares and returns the maximum of two values. Read more

Compares and returns the minimum of two values. Read more

Restrict a value to a certain interval. Read more

Returns a new box with a pclone() of this box’s contents.

Examples
use corundum::clone::PClone;

Heap::transaction(|j| {
    let x = Pbox::new(5, j);
    let y = x.pclone(j);
     
    // The value is the same
    assert_eq!(x, y);
     
    // But they are unique objects
    assert_ne!(&*x as *const i32, &*y as *const i32);
}).unwrap();

Performs copy-assignment from source. Read more

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

This method returns an ordering between self and other values if one exists. Read more

This method tests less than (for self and other) and is used by the < operator. Read more

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more

This method tests greater than or equal to (for self and other) and is used by the >= operator. Read more

This method tests greater than (for self and other) and is used by the > operator. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Converts the given value to a String. Read more

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.