Trait corundum::clone::PClone[][src]

pub trait PClone<A: MemPool>: Sized {
    fn pclone(&self, journal: &Journal<A>) -> Self;

    fn pclone_from(&mut self, source: &Self, journal: &Journal<A>) { ... }
}
Expand description

A common trait for the ability to explicitly duplicate an object.

Differs from Copy in that Copy is implicit and extremely inexpensive, while PClone is always explicit and may or may not be expensive. Its difference with Clone is that it a &Journal to be used for logging in Prc and Parc. In order to enforce these characteristics, Rust does not allow you to reimplement Copy, but you may reimplement Clone and PClone and run arbitrary code.

Since PClone is more general than Copy, you can automatically make anything Copy be Clone as well.

Derivable

This trait can be used with #[derive] if all fields are PClone. The derived implementation of PClone calls pclone on each field. It uses default::BuddyAlloc by default. It is possible to change the pool type(s) by using pools() attribute.

For a generic struct, #[derive] implements PClone conditionally by adding bound Clone on generic parameters.

// `derive` implements PClone<BuddyAlloc> for Reading<T> when T is 
// PClone<BuddyAlloc>
#[derive(PClone)]
struct Reading<T> {
    frequency: T,
}
// `derive` implements PClone<P> and PClone<Q> for Reading<T> when T is 
// PClone<P> and PClone<Q> specified by `pools`.
#[derive(PClone)]
#[pools(P,Q)]
struct Reading<T> {
    frequency: T,
}

How can I implement PClone?

Types that are Copy should have a trivial implementation of PClone. More formally: if T: Copy, x: T, and y: &T, then let x = y.pclone(); is equivalent to let x = *y;. Manual implementations should be careful to uphold this invariant; however, unsafe code must not rely on it to ensure memory safety. Note that, the implementation should be done for a specific (or generic) pool type.

Required methods

Provided methods

Performs copy-assignment from source.

a.clone_from(&b) is equivalent to a = b.clone() in functionality, but can be overridden to reuse the resources of a to avoid unnecessary allocations.

Implementations on Foreign Types

Implementors

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();

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));