Skip to main content

SnapshotLock

Struct SnapshotLock 

Source
pub struct SnapshotLock<T, Inner = RwLock<(T, usize)>> { /* private fields */ }
Expand description

A versioned lock implementation inspired by Multi-Version Concurrency Control (MVCC).

SnapshotLock provides concurrent access to data with lock-free reads and exclusive writes. It maintains multiple versions of the data to allow readers to access consistent snapshots without blocking writers.

§Type Parameters

  • T: The type of data being protected. Must be Clone. Surrounding lock is Send and Sync if T is Send

§Examples

use snaplock::SnapshotLock;

let lock = SnapshotLock::new(String::from("Hello"));

// Multiple readers can access the data concurrently
let reader1 = lock.read();
let reader2 = lock.read();
assert_eq!(*reader1, "Hello");
assert_eq!(*reader2, "Hello");

// Writers have exclusive access
let mut writer = lock.write();
writer.push_str(", World!");

// During write readers see old values
let reader3 = lock.read();
assert_eq!(*reader3, "Hello");
drop(writer);

// When write is finished, new readers see the updated value
let reader4 = lock.read();
assert_eq!(*reader4, "Hello, World!");

// Old readers still see their old value
assert_eq!(*reader1, "Hello");
assert_eq!(*reader2, "Hello");
assert_eq!(*reader3, "Hello");

Implementations§

Source§

impl<T: Clone> SnapshotLock<T, RwLock<(T, usize)>>

Source

pub fn new(inner: T) -> Self

Creates a new SnapshotLock with the initial value.

§Arguments
  • inner - The initial value to be protected by the lock.
§Examples
use snaplock::SnapshotLock;

let lock = SnapshotLock::new(42);
assert_eq!(*lock.read(), 42);
Source

pub fn write( &self, ) -> SnapshotLockWriteGuard<'_, T, RwLockWriteGuard<'_, (T, usize)>>

Acquires an exclusive write lock on the protected data.

This method blocks until no other writers hold the lock. The returned SnapshotLockWriteGuard allows mutable access to the data. When the guard is dropped, the version number is incremented and subsequent reads will see the updated value.

§Returns

A SnapshotLockWriteGuard that provides mutable access to the data.

§Examples
use snaplock::SnapshotLock;

let lock = SnapshotLock::new(0);
{
    let mut guard = lock.write();
    *guard = 42;
} // Guard dropped here, version incremented
assert_eq!(*lock.read(), 42);
Source

pub fn read(&self) -> SnapshotLockReadGuard<T>

Acquires a shared read lock on the protected data.

This method attempts to get the latest version of the data with minimal blocking. It first tries a non-blocking read of the current version, and if that fails or detects a newer version, it falls back to a cached snapshot.

§Returns

A SnapshotLockReadGuard that provides immutable access to a snapshot of the data.

§Examples
use snaplock::SnapshotLock;

let lock = SnapshotLock::new("data");
let guard = lock.read();
assert_eq!(*guard, "data");

Auto Trait Implementations§

§

impl<T, Inner = RwLock<(T, usize)>> !Freeze for SnapshotLock<T, Inner>

§

impl<T, Inner> RefUnwindSafe for SnapshotLock<T, Inner>

§

impl<T, Inner> Send for SnapshotLock<T, Inner>
where Inner: Send, ArcSwapAny<Arc<T>>: Send,

§

impl<T, Inner> Sync for SnapshotLock<T, Inner>
where Inner: Sync, ArcSwapAny<Arc<T>>: Sync,

§

impl<T, Inner> Unpin for SnapshotLock<T, Inner>
where Inner: Unpin, ArcSwapAny<Arc<T>>: Unpin,

§

impl<T, Inner> UnsafeUnpin for SnapshotLock<T, Inner>

§

impl<T, Inner> UnwindSafe for SnapshotLock<T, Inner>
where Inner: UnwindSafe, ArcSwapAny<Arc<T>>: UnwindSafe,

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 = !

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

fn try_from(value: U) -> Result<T, !>

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.