Struct corundum::stm::Chaperon[][src]

pub struct Chaperon { /* fields omitted */ }
Expand description

A third-party observer for multi-pool transactions

It provides an atomic supper transaction (a session) for manipulating persistent data in multiple pools, atomically. The involved pools go to a transient state when they call transaction inside a chaperoned session. The finalization functions (e.g. commit or rollback) are delayed until the end of the session. To keep track of pools’ states, it creates a chaperon file with necessary information for recovering them, in case of a crash.

Implementations

Loads a chaperon file

Returns the chaperon filename

Starts a chaperoned session

It creates a chaperoned session in which multiple pools can start a transaction. The transactions won’t be finalized until the session ends. A chaperon file keeps the necessary information for recovering the involved pools. If the operation is successful, it returns a value of type T.

Safety

  • In case of a crash, the involved pools are not individually recoverable on the absence of the chaperon file.
  • Chaperoned sessions cannot be nested.

Examples

use corundum::alloc::heap::*;
use corundum::stm::{Chaperon, Journal};
use corundum::cell::{PCell, RootObj};
use corundum::boxed::Pbox;

corundum::pool!(pool1);
corundum::pool!(pool2);

type P1 = pool1::BuddyAlloc;
type P2 = pool2::BuddyAlloc;

struct Root<M: MemPool> {
    val: Pbox<PCell<i32, M>, M>
}

impl<M: MemPool> RootObj<M> for Root<M> {
    fn init(j: &Journal<M>) -> Self {
        Root { val: Pbox::new(PCell::new(0), j) }
    }
}

let root1 = P1::open::<Root<P1>>("pool1.pool", O_CF).unwrap();
let root2 = P2::open::<Root<P2>>("pool2.pool", O_CF).unwrap();

let _=Chaperon::session("chaperon.pool", || {
    let v = P2::transaction(|j| {
        let old = root2.val.get();
        root2.val.set(old+1, j); // <-- should persist if both transactions commit
        old // <-- Send out p2's old data
    }).unwrap();
    P1::transaction(|j| {
        let mut p1 = root1.val.get();
        root1.val.set(p1+v, j);
    }).unwrap();
}).unwrap(); // <-- both transactions commit here

let v1 = root1.val.get();
let v2 = root2.val.get();
println!("root1 = {}", v1);
println!("root2 = {}", v2);
assert_eq!(v1, calc(v2-1));

fn calc(n: i32) -> i32 {
    if n < 1 {
        0
    } else {
        n + calc(n-1)
    }
}

Trait Implementations

Formats the value using the given formatter. Read more

Executes the destructor for this type. 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

Performs the conversion.

Performs the conversion.

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.