Skip to main content

LockKp

Struct LockKp 

Source
pub struct LockKp<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2>
where Root: Borrow<R>, LockValue: Borrow<Lock>, MidValue: Borrow<Mid>, Value: Borrow<V>, MutRoot: BorrowMut<R>, MutLock: BorrowMut<Lock>, MutMid: BorrowMut<Mid>, MutValue: BorrowMut<V>, G1: Fn(Root) -> Option<LockValue>, S1: Fn(MutRoot) -> Option<MutLock>, L: LockAccess<Lock, MidValue> + LockAccess<Lock, MutMid>, G2: Fn(MidValue) -> Option<Value>, S2: Fn(MutMid) -> Option<MutValue>,
{ /* private fields */ }
Expand description

A keypath that handles locked values (e.g., Arc<Mutex>)

Structure:

  • prev: Keypath from Root to Lock container (e.g., Arc<Mutex>)
  • mid: Lock access handler that goes from Lock to Inner value
  • next: Keypath from Inner value to final Value

§Type Parameters

  • R: Root type (base)
  • Lock: Lock container type (e.g., Arc<Mutex>)
  • Mid: The type inside the lock
  • V: Final value type
  • Rest are the same generic parameters as Kp

§Cloning Behavior

IMPORTANT: All Clone operations in this struct are SHALLOW clones:

  • LockKp itself derives Clone - this clones the three field references/closures
  • prev and next fields are Kp structs containing function pointers (cheap to clone)
  • mid field implements LockAccess trait - typically just PhantomData (zero-cost clone)
  • NO Lock: Clone needed for lock operations - we use &Lock directly via interior mutability
  • NO deep data cloning occurs - all clones are pointer/reference copies

§Example

use std::sync::{Arc, Mutex};
use rust_key_paths::lock::{ArcMutexAccess, LockKp};
use rust_key_paths::Kp;

struct Root {
    data: Arc<Mutex<Inner>>,
}

struct Inner {
    value: String,
}

// Create a LockKp that goes: Root -> Arc<Mutex<Inner>> -> String
let root_to_lock_kp = Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let inner_to_value_kp = Kp::new(|i: &Inner| Some(&i.value), |i: &mut Inner| Some(&mut i.value));
let lock_kp = LockKp::new(root_to_lock_kp, ArcMutexAccess::new(), inner_to_value_kp);

Implementations§

Source§

impl<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2> LockKp<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2>
where Root: Borrow<R>, LockValue: Borrow<Lock>, MidValue: Borrow<Mid>, Value: Borrow<V>, MutRoot: BorrowMut<R>, MutLock: BorrowMut<Lock>, MutMid: BorrowMut<Mid>, MutValue: BorrowMut<V>, G1: Fn(Root) -> Option<LockValue>, S1: Fn(MutRoot) -> Option<MutLock>, L: LockAccess<Lock, MidValue> + LockAccess<Lock, MutMid>, G2: Fn(MidValue) -> Option<Value>, S2: Fn(MutMid) -> Option<MutValue>,

Source

pub fn new( prev: Kp<R, Lock, Root, LockValue, MutRoot, MutLock, G1, S1>, mid: L, next: Kp<Mid, V, MidValue, Value, MutMid, MutValue, G2, S2>, ) -> Self

Create a new LockKp with prev, mid, and next components

Source

pub fn get(&self, root: Root) -> Option<Value>
where V: Clone,

Get an immutable reference through the lock (sync, blocking).

This will:

  1. Use prev to get to the Lock
  2. Use mid to lock and get Inner value
  3. Use next to get from Inner to final Value
§Example
use rust_key_paths::{KpType, LockKp};
use std::sync::Mutex;

#[derive(key_paths_derive::Kp)]
struct WithLocks {
    std_mutex: std::sync::Mutex<i32>,
    std_rwlock: std::sync::RwLock<String>,
}

let locks = WithLocks {
    std_mutex: Mutex::new(99),
    std_rwlock: std::sync::RwLock::new("test".to_string()),
};
let mutex_kp = WithLocks::std_mutex();
let rwlock_kp = WithLocks::std_rwlock();
let next: KpType<i32, i32> = rust_key_paths::Kp::new(|i: &i32| Some(i), |i: &mut i32| Some(i));
let lock_kp = LockKp::new(mutex_kp, rust_key_paths::StdMutexAccess::new(), next);

let value = lock_kp.get(&locks);
assert_eq!(value, Some(&99));
§Cloning Behavior

Only requires V: Clone for the final value. NO Lock: Clone needed because lock_read takes &Lock.

Source

pub fn get_mut(&self, root: MutRoot) -> Option<MutValue>

Get mutable access to the value through the lock (sync, blocking).

§Example
use rust_key_paths::{KpType, LockKp};
use std::sync::Mutex;

#[derive(key_paths_derive::Kp)]
struct WithLocks {
    std_mutex: std::sync::Mutex<i32>,
    std_rwlock: std::sync::RwLock<String>,
}

let mut locks = WithLocks {
    std_mutex: Mutex::new(99),
    std_rwlock: std::sync::RwLock::new("test".to_string()),
};
let mutex_kp = WithLocks::std_mutex();
let next: KpType<i32, i32> = rust_key_paths::Kp::new(|i: &i32| Some(i), |i: &mut i32| Some(i));
let lock_kp = LockKp::new(mutex_kp, rust_key_paths::StdMutexAccess::new(), next);

let value = lock_kp.get_mut(&mut locks).unwrap();
*value = 42;
assert_eq!(*locks.std_mutex.lock().unwrap(), 42);
§NO CLONING Required!

No longer needs Lock: Clone because lock_write now takes &Lock instead of &mut Lock

Source

pub fn set<F>(&self, root: Root, updater: F) -> Result<(), String>
where F: FnOnce(&mut V), MutValue: BorrowMut<V>,

Set the value through the lock using an updater function

§NO CLONING Required!

Unlike the original implementation, we NO LONGER need Lock: Clone because:

  • Locks like Mutex and RwLock provide interior mutability
  • We only need &Lock, not &mut Lock, to get mutable access to the inner data
  • This eliminates an unnecessary Arc reference count increment
Source

pub fn then<V2, Value2, MutValue2, G3, S3>( self, next_kp: Kp<V, V2, Value, Value2, MutValue, MutValue2, G3, S3>, ) -> LockKp<R, Lock, Mid, V2, Root, LockValue, MidValue, Value2, MutRoot, MutLock, MutMid, MutValue2, G1, S1, L, impl Fn(MidValue) -> Option<Value2> + use<G1, G2, G3, L, Lock, LockValue, Mid, MidValue, MutLock, MutMid, MutRoot, MutValue, MutValue2, R, Root, S1, S2, S3, Value, Value2, V, V2>, impl Fn(MutMid) -> Option<MutValue2> + use<G1, G2, G3, L, Lock, LockValue, Mid, MidValue, MutLock, MutMid, MutRoot, MutValue, MutValue2, R, Root, S1, S2, S3, Value, Value2, V, V2>>
where V: 'static, V2: 'static, Value: Borrow<V>, Value2: Borrow<V2>, MutValue: BorrowMut<V>, MutValue2: BorrowMut<V2>, G3: Fn(Value) -> Option<Value2> + 'static, S3: Fn(MutValue) -> Option<MutValue2> + 'static,

Chain this LockKp with another regular Kp

This allows you to continue navigating after getting through the lock: Root -> Lock -> Mid -> Value1 -> Value2

§Cloning Behavior

No cloning occurs in this method - closures are moved into the new Kp

Source

pub fn then_lock<Lock2, Mid2, V2, LockValue2, MidValue2, Value2, MutLock2, MutMid2, MutValue2, G2_1, S2_1, L2, G2_2, S2_2>( self, other: LockKp<V, Lock2, Mid2, V2, Value, LockValue2, MidValue2, Value2, MutValue, MutLock2, MutMid2, MutValue2, G2_1, S2_1, L2, G2_2, S2_2>, ) -> LockKp<R, Lock, Mid, V2, Root, LockValue, MidValue, Value2, MutRoot, MutLock, MutMid, MutValue2, G1, S1, L, impl Fn(MidValue) -> Option<Value2> + use<G1, G2, G2_1, G2_2, L, L2, Lock, Lock2, LockValue, LockValue2, Mid, Mid2, MidValue, MidValue2, MutLock, MutLock2, MutMid, MutMid2, MutRoot, MutValue, MutValue2, R, Root, S1, S2, S2_1, S2_2, Value, Value2, V, V2>, impl Fn(MutMid) -> Option<MutValue2> + use<G1, G2, G2_1, G2_2, L, L2, Lock, Lock2, LockValue, LockValue2, Mid, Mid2, MidValue, MidValue2, MutLock, MutLock2, MutMid, MutMid2, MutRoot, MutValue, MutValue2, R, Root, S1, S2, S2_1, S2_2, Value, Value2, V, V2>>
where V: 'static + Clone, V2: 'static, Value: Borrow<V>, LockValue2: Borrow<Lock2>, MidValue2: Borrow<Mid2>, Value2: Borrow<V2>, MutValue: BorrowMut<V>, MutLock2: BorrowMut<Lock2>, MutMid2: BorrowMut<Mid2>, MutValue2: BorrowMut<V2>, G2_1: Fn(Value) -> Option<LockValue2> + 'static, S2_1: Fn(MutValue) -> Option<MutLock2> + 'static, L2: LockAccess<Lock2, MidValue2> + LockAccess<Lock2, MutMid2> + Clone + 'static, G2_2: Fn(MidValue2) -> Option<Value2> + 'static, S2_2: Fn(MutMid2) -> Option<MutValue2> + 'static,

Chain with another LockKp for multi-level lock access (then_lock convention)

This allows you to chain through multiple lock levels: Root -> Lock1 -> Mid1 -> Lock2 -> Mid2 -> Value

§Cloning Behavior - ALL CLONES ARE SHALLOW

This method requires two types of cloning, both SHALLOW:

  1. L2: Clone: Clones the lock accessor (typically PhantomData)

    • For ArcMutexAccess<T>: Only clones PhantomData (zero-cost)
    • No data is cloned, just the lock access behavior
  2. NO Lock2: Clone needed: Uses &Lock2 reference directly (interior mutability)

Performance: Only L2 (lock accessor) is cloned—O(1), typically zero-cost PhantomData

§Example
// Root -> Arc<Mutex<Mid1>> -> Mid1 -> Arc<Mutex<Mid2>> -> Mid2 -> String
let lock_kp1 = LockKp::new(root_to_lock1, ArcMutexAccess::new(), lock1_to_mid1);
let lock_kp2 = LockKp::new(mid1_to_lock2, ArcMutexAccess::new(), mid2_to_value);

let chained = lock_kp1.then_lock(lock_kp2);
Source

pub fn then_async<AsyncKp>( self, async_kp: AsyncKp, ) -> KpThenAsyncKeyPath<R, V, <AsyncKp::Value as KeyPathValueTarget>::Target, Root, Value, AsyncKp::Value, MutRoot, MutValue, AsyncKp::MutValue, Self, AsyncKp>
where V: 'static + Clone, Value: Borrow<V>, MutValue: BorrowMut<V>, AsyncKp: AsyncKeyPathLike<Value, MutValue>, AsyncKp::Value: KeyPathValueTarget + Borrow<<AsyncKp::Value as KeyPathValueTarget>::Target>, AsyncKp::MutValue: BorrowMut<<AsyncKp::Value as KeyPathValueTarget>::Target>, <AsyncKp::Value as KeyPathValueTarget>::Target: 'static,

Chain with an async keypath. Use .get(&root).await on the returned keypath. When AsyncKp::Value is a reference type (&T / &mut T), V2 is inferred as T via crate::KeyPathValueTarget.

Trait Implementations§

Source§

impl<R: Clone, Lock: Clone, Mid: Clone, V: Clone, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2> Clone for LockKp<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2>
where Root: Borrow<R> + Clone, LockValue: Borrow<Lock> + Clone, MidValue: Borrow<Mid> + Clone, Value: Borrow<V> + Clone, MutRoot: BorrowMut<R> + Clone, MutLock: BorrowMut<Lock> + Clone, MutMid: BorrowMut<Mid> + Clone, MutValue: BorrowMut<V> + Clone, G1: Fn(Root) -> Option<LockValue> + Clone, S1: Fn(MutRoot) -> Option<MutLock> + Clone, L: LockAccess<Lock, MidValue> + LockAccess<Lock, MutMid> + Clone, G2: Fn(MidValue) -> Option<Value> + Clone, S2: Fn(MutMid) -> Option<MutValue> + Clone,

Source§

fn clone( &self, ) -> LockKp<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2>

Returns a duplicate of the value. Read more
1.0.0 · Source§

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

Performs copy-assignment from source. Read more
Source§

impl<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2> SyncKeyPathLike<Root, Value, MutRoot, MutValue> for LockKp<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2>
where Root: Borrow<R>, LockValue: Borrow<Lock>, MidValue: Borrow<Mid>, Value: Borrow<V>, MutRoot: BorrowMut<R>, MutLock: BorrowMut<Lock>, MutMid: BorrowMut<Mid>, MutValue: BorrowMut<V>, G1: Fn(Root) -> Option<LockValue>, S1: Fn(MutRoot) -> Option<MutLock>, L: LockAccess<Lock, MidValue> + LockAccess<Lock, MutMid>, G2: Fn(MidValue) -> Option<Value>, S2: Fn(MutMid) -> Option<MutValue>, V: Clone,

Source§

fn sync_get(&self, root: Root) -> Option<Value>

Get an immutable reference through the keypath (sync, non-blocking). Read more
Source§

fn sync_get_mut(&self, root: MutRoot) -> Option<MutValue>

Get a mutable reference through the keypath (sync, non-blocking). Read more

Auto Trait Implementations§

§

impl<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2> Freeze for LockKp<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2>
where L: Freeze, G1: Freeze, S1: Freeze, G2: Freeze, S2: Freeze,

§

impl<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2> RefUnwindSafe for LockKp<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2>

§

impl<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2> Send for LockKp<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2>
where L: Send, G1: Send, S1: Send, G2: Send, S2: Send, R: Send, Lock: Send, Root: Send, LockValue: Send, MutRoot: Send, MutLock: Send, Mid: Send, V: Send, MidValue: Send, Value: Send, MutMid: Send, MutValue: Send,

§

impl<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2> Sync for LockKp<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2>
where L: Sync, G1: Sync, S1: Sync, G2: Sync, S2: Sync, R: Sync, Lock: Sync, Root: Sync, LockValue: Sync, MutRoot: Sync, MutLock: Sync, Mid: Sync, V: Sync, MidValue: Sync, Value: Sync, MutMid: Sync, MutValue: Sync,

§

impl<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2> Unpin for LockKp<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2>
where L: Unpin, G1: Unpin, S1: Unpin, G2: Unpin, S2: Unpin, R: Unpin, Lock: Unpin, Root: Unpin, LockValue: Unpin, MutRoot: Unpin, MutLock: Unpin, Mid: Unpin, V: Unpin, MidValue: Unpin, Value: Unpin, MutMid: Unpin, MutValue: Unpin,

§

impl<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2> UnwindSafe for LockKp<R, Lock, Mid, V, Root, LockValue, MidValue, Value, MutRoot, MutLock, MutMid, MutValue, G1, S1, L, G2, S2>
where L: UnwindSafe, G1: UnwindSafe, S1: UnwindSafe, G2: UnwindSafe, S2: UnwindSafe, R: UnwindSafe, Lock: UnwindSafe, Root: UnwindSafe, LockValue: UnwindSafe, MutRoot: UnwindSafe, MutLock: UnwindSafe, Mid: UnwindSafe, V: UnwindSafe, MidValue: UnwindSafe, Value: UnwindSafe, MutMid: UnwindSafe, MutValue: 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, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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.