pairlock

Struct PairLock

Source
pub struct PairLock<T> { /* private fields */ }
Expand description

A reader-writer lock with wait-free reads.

Does not have poisoning.

§Examples

let ac = Arc::new(PairLock::new_arc(load_config()));
let ac2 = ac.clone();
thread::spawn(move|| {
    loop {
        use_config(ac2.get());;
    }
});
loop {
    thread::sleep(Duration::from_secs(60));
    ac.set(Arc::new(load_config()));
}

Implementations§

Source§

impl<T> PairLock<T>

Source

pub fn new(active: T, inactive: T) -> Self

Creates a new PairLock.

Source

pub fn with_default(init: T) -> Self
where T: Default,

Creates a new PairLock with init as the active value and T’s default value as the inactive.

Source

pub fn with_clone(init: T) -> Self
where T: Clone,

Creates a new PairLock with init as the active value and its .clone() as the inactive.

Source

pub fn view<F: FnOnce(&T) -> R, R>(&self, viewer: F) -> R

View the active value of this PairLock inside a closure.

Views should be short-lived to avoid blocking subsequent updates.

Reads must be performed inside a closure, because preventing memory unsafety in the face of repeated mem::forget()s of a read guard is non-trivial.

Will never block in any way, and should run in constant time.

Source

pub fn get_clone(&self) -> T
where T: Clone,

Returns a clone of the active value.

Will never block in any way, and should run in constant time.

Source

pub fn update(&self) -> UpdateGuard<'_, T>

Locks the inactive value, giving exclusive access to it through a RAII guard that will make it active when the guard is dropped.

Will block the thread waiting for reads of the inactive value or other updates to finish.

Panicing while holding the guard does not poison the lock.

§Examples

Using the lock as a counter

let counter = PairLock::with_default(1);
let mut guard = counter.update();
*guard = UpdateGuard::active(&guard) + 1;
drop(guard);
assert_eq!(counter.read(), 2);

Reusing an allocation while updating

let lock = PairLock::with_default(vec!["foo","bar"]);
let mut guard = lock.update();
{
    let (mutable, active) = UpdateGuard::both(&mut guard);
    mutable.clone_from(active);
    mutable.push("baz");
}
drop(guard);
lock.view(|v| assert_eq!(v[..], ["foo","bar","baz"][..]) );

Doing nothing with the guard, and still changing the value of the lock:

let lock = PairLock::new("foo", "bar");
assert_eq!(lock.read(), "foo");
let _ = lock.update();
assert_eq!(lock.read(), "bar");
Source

pub fn try_update(&self) -> Result<UpdateGuard<'_, T>, TryUpdateError>

Attempts to lock the inactive value, giving exclusive access to it through a RAII guard that will make it active when the guard is dropped.

§Errors

Returns an error instead of blocking the thread.
The error tells which phase of aquiring the update lock that failed.

§Examples
let pl = PairLock::new(String::new(), String::new());
let _guard = pl.try_update().unwrap();
assert_eq!(pl.try_update(), Err(TryUpdateError::OtherUpdate));
Source

pub fn set(&self, value: T) -> T

Stores a new value in the PairLock, returning the previously inactive value.

Will block if another update/replace/set is in progress. if there are reads of the second last value that haven’t finished yet.

Source

pub fn into_inner(self) -> (T, T)

Consumes the PairLock and returns the active and inactive values.

§Examples
let lock = PairLock::new(true, false);
let (active, inactive) = lock.into_inner();
Source

pub fn get_mut_both(&mut self) -> (&mut T, &mut T)

Given exclusive access this method returns mutable references to both the active and inactive value.

§Examples
let mut lock = PairLock::new(true, false);
let (&mut active, &mut inactive) = lock.get_mut_both();
Source

pub fn get_mut_active(&mut self) -> &mut T

Given exclusive access this method returns a mutable reference to the active value.

Source

pub fn get_mut_inactive(&mut self) -> &mut T

Given exclusive access this method returns a mutable reference to the inactive value.

Source§

impl<T> PairLock<Arc<T>>

Source

pub fn new_arc(value: T) -> Self

Puts value into an Arc<T> and creates a new PairLock<Arc<T>> with it.

Source§

impl<T: ?Sized> PairLock<Arc<T>>

Source

pub fn get(&self) -> Arc<T>

Returns a clone of the active Arc<T>.

Will never block in any way, and should run in constant time.

Source§

impl<T: Copy> PairLock<T>

Source

pub fn read(&self) -> T

Returns a copy of the active value.

Will never block in any way, and should run in constant time.

Trait Implementations§

Source§

impl<T: Clone> Clone for PairLock<T>

Source§

fn clone(&self) -> Self

Returns a new PairLock initialized with the current Arc in self.

Does not clone the content of the Arc.

Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: Debug> Debug for PairLock<T>

Source§

fn fmt(&self, fmtr: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: Default> Default for PairLock<T>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<T: Send> Send for PairLock<T>

Source§

impl<T: Send + Sync> Sync for PairLock<T>

T must be Send because a shared reference can replace stored values.

Auto Trait Implementations§

§

impl<T> !Freeze for PairLock<T>

§

impl<T> !RefUnwindSafe for PairLock<T>

§

impl<T> Unpin for PairLock<T>
where T: Unpin,

§

impl<T> UnwindSafe for PairLock<T>
where 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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.