#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Transaction;
impl Transaction
{
#[inline(always)]
pub fn transaction<Committed: Sized, Aborted: Sized, W: Fn(Transaction) -> c_int, C: Fn() -> Committed, A: Fn() -> Aborted>(pop: *mut PMEMobjpool, work: W, onCommit: C, onAbort: A) -> Result<Committed, Aborted>
{
#[inline(never)]
unsafe fn internal
<
Committed: Sized,
Aborted: Sized,
W: Fn(Transaction) -> c_int,
C: Fn() -> Committed,
A: Fn() -> Aborted
>
(
pop: *mut PMEMobjpool,
work: W,
onCommit: C,
onAbort: A,
panicPayload: &mut Option<Box<Any + Send + 'static>>,
functionResult: &mut Option<Result<Committed, Aborted>>
)
{
let txSetJmpEnvironment = zeroed();
{
if setjmp(txSetJmpEnvironment) == 0
{
setErrorNumberIfNecessary(pmemobj_tx_begin(pop, txSetJmpEnvironment, TX_PARAM_NONE, TX_PARAM_NONE));
}
else
{
setErrorNumberIfNecessary(pmemobj_tx_errno());
}
let mut stage;
while
{
stage = pmemobj_tx_stage();
stage != pobj_tx_stage::TX_STAGE_NONE
}
{
match stage
{
pobj_tx_stage::TX_STAGE_WORK =>
{
let PanicOsErrorNumber: c_int = E::ENOTSUP;
match catch_unwind(AssertUnwindSafe(|| work(Transaction)))
{
Ok(someOsErrorNumberForAbort) =>
{
if likely(someOsErrorNumberForAbort == 0)
{
pmemobj_tx_commit();
}
else
{
pmemobj_tx_abort(PanicOsErrorNumber);
}
},
Err(payload) =>
{
pmemobj_tx_abort(PanicOsErrorNumber);
*panicPayload = Some(payload);
},
};
pmemobj_tx_process();
},
pobj_tx_stage::TX_STAGE_ONCOMMIT =>
{
match catch_unwind(AssertUnwindSafe(|| onCommit()))
{
Ok(result) =>
{
*functionResult = Some(Ok(result))
},
Err(payload) =>
{
if panicPayload.is_none()
{
*panicPayload = Some(payload)
}
}
};
pmemobj_tx_process();
},
pobj_tx_stage::TX_STAGE_ONABORT =>
{
match catch_unwind(AssertUnwindSafe(|| onAbort()))
{
Ok(result) =>
{
*functionResult = Some(Err(result))
},
Err(payload) =>
{
if panicPayload.is_none()
{
*panicPayload = Some(payload)
}
}
};
pmemobj_tx_process();
},
pobj_tx_stage::TX_STAGE_FINALLY =>
{
pmemobj_tx_process();
},
_ =>
{
pmemobj_tx_process();
},
}
}
pmemobj_tx_end();
setErrorNumberIfNecessary(pmemobj_tx_end());
}
}
let mut panicPayload = None;
let mut functionResult = None;
unsafe { internal(pop, work, onCommit, onAbort, &mut panicPayload, &mut functionResult) };
if let Some(payload) = panicPayload
{
resume_unwind(payload);
}
functionResult.unwrap()
}
}
#[inline(always)]
fn setErrorNumberIfNecessary(osErrorNumber: c_int)
{
if unlikely(osErrorNumber != 0)
{
set_errno(Errno(osErrorNumber));
}
}