Skip to main content

FMTransaction

Struct FMTransaction 

Source
pub struct FMTransaction<'a, T> { /* private fields */ }
Expand description

A context for grouping multi write ops into a single atomic operation

§Overview

Use of FMTransaction allows to group multiple write ops into a single atomic operation.

  • All included writes are applied together
  • Single epoch is assinged for an entier transaction
  • Durability guarantee is same for all included write ops

§Example

use frozen_core::fmmap::{FrozenMMap, FrozenMMapCfg};

const MODULE_ID: u8 = 0;

let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("tmp_tx");

let cfg = FrozenMMapCfg {
    module_id: MODULE_ID,
    initial_count: 0x0A,
    flush_duration: std::time::Duration::from_micros(50),
};

let mmap = FrozenMMap::<u64>::new(&path, cfg).unwrap();

let mut tx = mmap.new_tx();
unsafe { tx.write(0, |v| *v = 0x0A) }.unwrap();
unsafe { tx.write(1, |v| *v = 0x14) }.unwrap();
unsafe { tx.write(2, |v| *v = 0x18) }.unwrap();

let epoch = tx.commit().unwrap();
mmap.wait_for_durability(epoch).unwrap();

let v0 = unsafe { mmap.read(0, |v| *v).unwrap() };
let v1 = unsafe { mmap.read(1, |v| *v).unwrap() };
let v2 = unsafe { mmap.read(2, |v| *v).unwrap() };

assert_eq!((v0, v1, v2), (0x0A, 0x14, 0x18));

Implementations§

Source§

impl<'a, T> FMTransaction<'a, T>

Source

pub unsafe fn write<F>(&mut self, index: usize, f: F) -> FrozenResult<()>
where F: FnOnce(*mut T) + 'a,

Append a write op into the FMTransaction

§Requirements

Write ops must follow these safety requirements,

  • No duplicate indices
  • No out-of-order writes (must be incremental)

Violating this constraint would result in FrozenError

§Safety

Same safety requirements as FrozenMMap::write apply here

§Example
use frozen_core::fmmap::{FrozenMMap, FrozenMMapCfg};

const MODULE_ID: u8 = 0;

let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("tmp_tx");

let cfg = FrozenMMapCfg {
    module_id: MODULE_ID,
    initial_count: 0x10,
    flush_duration: std::time::Duration::from_micros(50),
};

let mmap = FrozenMMap::<u64>::new(&path, cfg).unwrap();

let mut tx = mmap.new_tx();
unsafe { tx.write(0, |v| *v = 0x0A) }.unwrap();
unsafe { tx.write(1, |v| *v = 0x0B) }.unwrap();
unsafe { tx.write(2, |v| *v = 0x0C) }.unwrap();

let epoch = tx.commit().unwrap();
mmap.wait_for_durability(epoch).unwrap();

let v0 = unsafe { mmap.read(0, |v| *v).unwrap() };
let v1 = unsafe { mmap.read(1, |v| *v).unwrap() };
let v2 = unsafe { mmap.read(2, |v| *v).unwrap() };

assert_eq!((v0, v1, v2), (0x0A, 0x0B, 0x0C));
Source

pub fn commit(self) -> FrozenResult<u64>

Commit the transaction, applying all the writes ops, combined into a single atomic operation

§Guarantees
  • All writes are applied under a single epoch
  • All writes belong to the same durability batch
  • No interleaving with other transactions at epoch level
§Example
use frozen_core::fmmap::{FrozenMMap, FrozenMMapCfg};

const MODULE_ID: u8 = 0;

let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("tmp_tx");

let cfg = FrozenMMapCfg {
    module_id: MODULE_ID,
    initial_count: 0x10,
    flush_duration: std::time::Duration::from_micros(50),
};

let mmap = FrozenMMap::<u64>::new(&path, cfg).unwrap();

let mut tx = mmap.new_tx();
unsafe { tx.write(0, |v| *v = 0x0A) }.unwrap();
unsafe { tx.write(2, |v| *v = 0x0C) }.unwrap();

let epoch = tx.commit().unwrap();
mmap.wait_for_durability(epoch).unwrap();

let v0 = unsafe { mmap.read(0, |v| *v).unwrap() };
let v1 = unsafe { mmap.read(2, |v| *v).unwrap() };

assert_eq!((v0, v1), (0x0A, 0x0C));

Auto Trait Implementations§

§

impl<'a, T> !RefUnwindSafe for FMTransaction<'a, T>

§

impl<'a, T> !Send for FMTransaction<'a, T>

§

impl<'a, T> !Sync for FMTransaction<'a, T>

§

impl<'a, T> !UnwindSafe for FMTransaction<'a, T>

§

impl<'a, T> Freeze for FMTransaction<'a, T>

§

impl<'a, T> Unpin for FMTransaction<'a, T>

§

impl<'a, T> UnsafeUnpin for FMTransaction<'a, T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.