[][src]Struct crndm::stm::Chaperon

pub struct Chaperon { /* fields omitted */ }

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

impl Chaperon[src]

pub unsafe fn load(filename: String) -> Result<&'static mut Self>[src]

Loads a chaperon file

pub fn filename(&self) -> &str[src]

Returns the chaperon filename

pub fn session<T, F: FnOnce() -> T>(filename: &str, body: F) -> Result<T> where
    F: UnwindSafe,
    T: UnwindSafe + TxOutSafe
[src]

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 crndm::alloc::*;
use crndm::stm::*;
use crndm::cell::*;
use crndm::boxed::*;

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

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

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

impl<M: MemPool> RootObj<M> for Root<M> {
    fn init(j: &Journal<M>) -> Self {
        Root { val: Pbox::new(LogCell::new(0, j), 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

impl Debug for Chaperon[src]

impl Drop for Chaperon[src]

impl RefUnwindSafe for Chaperon[src]

impl Send for Chaperon[src]

impl Sync for Chaperon[src]

impl TxInSafe for Chaperon[src]

impl !TxOutSafe for Chaperon[src]

impl UnwindSafe for Chaperon[src]

Auto Trait Implementations

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, 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>,