pub fn session<T, F: FnOnce() -> T>(filename: &str, body: F) -> Result<T>
    where
        F: panic::UnwindSafe,
        T: panic::UnwindSafe + TxOutSafe,
    {
        let chaperon = unsafe { &mut *new_chaperon(filename)? };
        let res = panic::catch_unwind(|| body());
        if let Ok(res) = res {
            chaperon.execute_delayed_commits();
            drop_chaperon();
            Ok(res)
        } else {
            chaperon.execute_delayed_rollbacks();
            drop_chaperon();
            Err("Unsuccessful chaperoned transaction".to_string())
        }
    }
/// 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::Allocator;
/// type P2 = pool2::Allocator;
///
/// 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)
///     }
/// }
/// ```
/// 
/// [`transaction`]: ./fn.transaction.html
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`.
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 ` .
pub fn session<T, F: FnOnce() -> T>(filename: &str, body: F) -> Result<T>
    where
        F: panic::UnwindSafe,
        T: panic::UnwindSafe + TxOutSafe,
    {
        let chaperon = unsafe { &mut *new_chaperon(filename)? };
        let res = panic::catch_unwind(|| body());
        if let Ok(res) = res {
            chaperon.execute_delayed_commits();
            drop_chaperon();
            Ok(res)
        } else {
            chaperon.execute_delayed_rollbacks();
            drop_chaperon();
            Err("Unsuccessful chaperoned transaction".to_string())
        }
    }
pub fn session < T , F : FnOnce ( ) -> T > ( filename : & str , body : F ) -> Result < T > where F : panic :: UnwindSafe , T : panic :: UnwindSafe + TxOutSafe , { let chaperon = unsafe { & mut * new_chaperon ( filename ) ? } ; let res = panic :: catch_unwind ( | | body ( ) ) ; if let Ok ( res ) = res { chaperon . execute_delayed_commits ( ) ; drop_chaperon ( ) ; Ok ( res ) } else { chaperon . execute_delayed_rollbacks ( ) ; drop_chaperon ( ) ; Err ( " " . to_string ( ) ) } }
Starts a chaperoned session
It creates a chaperoned session in which multiple pools can start a
[`transaction`].
Starts a chaperoned session It creates a chaperoned session in which multiple pools can start a [ ` transaction ` ] .
filename
&str
body
F
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.
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.



type P1 = pool1::Allocator;
type P2 = pool2::Allocator.

struct Root {
val: Pbox, M>
}

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



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





[`transaction`]: ./fn.transaction.html
` ` ` use corundum :: alloc :: heap :: * ; use corundum :: stm :: { Chaperon Journal } ; use corundum :: cell :: { PCell RootObj } ; use corundum :: boxed :: Pbox . type P1 = pool1 :: Allocator ; type P2 = pool2 :: Allocator . struct Root { val : Pbox M > } impl RootObj for Root { fn init ( j : &Journal ) - > Self { Root { val : Pbox :: new ( PCell :: new ( 0 ) j ) } } } 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 [ ` transaction ` ] : . / fn . transaction . html