use crate::Kp;
use std::fmt;
use std::sync::{Arc, Mutex};
pub trait LockAccess<Lock, Inner> {
fn lock_read(&self, lock: &Lock) -> Option<Inner>;
fn lock_write(&self, lock: &Lock) -> Option<Inner>;
}
#[derive(Clone)] pub struct LockKp<
R,
Lock,
Mid,
V,
Root,
LockValue,
MidValue,
Value,
MutRoot,
MutLock,
MutMid,
MutValue,
G1,
S1,
L,
G2,
S2,
> where
Root: std::borrow::Borrow<R>,
LockValue: std::borrow::Borrow<Lock>,
MidValue: std::borrow::Borrow<Mid>,
Value: std::borrow::Borrow<V>,
MutRoot: std::borrow::BorrowMut<R>,
MutLock: std::borrow::BorrowMut<Lock>,
MutMid: std::borrow::BorrowMut<Mid>,
MutValue: std::borrow::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>,
{
pub(crate) prev: Kp<R, Lock, Root, LockValue, MutRoot, MutLock, G1, S1>,
pub(crate) mid: L,
pub(crate) next: Kp<Mid, V, MidValue, Value, MutMid, MutValue, G2, S2>,
}
impl<
R,
Lock,
Mid,
V,
Root,
LockValue,
MidValue,
Value,
MutRoot,
MutLock,
MutMid,
MutValue,
G1,
S1,
L,
G2,
S2,
> fmt::Debug
for LockKp<
R,
Lock,
Mid,
V,
Root,
LockValue,
MidValue,
Value,
MutRoot,
MutLock,
MutMid,
MutValue,
G1,
S1,
L,
G2,
S2,
>
where
Root: std::borrow::Borrow<R>,
LockValue: std::borrow::Borrow<Lock>,
MidValue: std::borrow::Borrow<Mid>,
Value: std::borrow::Borrow<V>,
MutRoot: std::borrow::BorrowMut<R>,
MutLock: std::borrow::BorrowMut<Lock>,
MutMid: std::borrow::BorrowMut<Mid>,
MutValue: std::borrow::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>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("LockKp")
.field("root_ty", &std::any::type_name::<R>())
.field("lock_ty", &std::any::type_name::<Lock>())
.field("mid_ty", &std::any::type_name::<Mid>())
.field("value_ty", &std::any::type_name::<V>())
.finish_non_exhaustive()
}
}
impl<
R,
Lock,
Mid,
V,
Root,
LockValue,
MidValue,
Value,
MutRoot,
MutLock,
MutMid,
MutValue,
G1,
S1,
L,
G2,
S2,
> fmt::Display
for LockKp<
R,
Lock,
Mid,
V,
Root,
LockValue,
MidValue,
Value,
MutRoot,
MutLock,
MutMid,
MutValue,
G1,
S1,
L,
G2,
S2,
>
where
Root: std::borrow::Borrow<R>,
LockValue: std::borrow::Borrow<Lock>,
MidValue: std::borrow::Borrow<Mid>,
Value: std::borrow::Borrow<V>,
MutRoot: std::borrow::BorrowMut<R>,
MutLock: std::borrow::BorrowMut<Lock>,
MutMid: std::borrow::BorrowMut<Mid>,
MutValue: std::borrow::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>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"LockKp<{}, {}, {}, {}>",
std::any::type_name::<R>(),
std::any::type_name::<Lock>(),
std::any::type_name::<Mid>(),
std::any::type_name::<V>()
)
}
}
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: std::borrow::Borrow<R>,
LockValue: std::borrow::Borrow<Lock>,
MidValue: std::borrow::Borrow<Mid>,
Value: std::borrow::Borrow<V>,
MutRoot: std::borrow::BorrowMut<R>,
MutLock: std::borrow::BorrowMut<Lock>,
MutMid: std::borrow::BorrowMut<Mid>,
MutValue: std::borrow::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>,
{
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 {
Self { prev, mid, next }
}
#[inline]
pub fn get(&self, root: Root) -> Option<Value>
where
V: Clone,
{
(self.prev.get)(root).and_then(|lock_value| {
let lock: &Lock = lock_value.borrow();
self.mid
.lock_read(lock)
.and_then(|mid_value| (self.next.get)(mid_value))
})
}
#[inline]
pub fn get_mut(&self, root: MutRoot) -> Option<MutValue> {
(self.prev.set)(root).and_then(|lock_value| {
let lock: &Lock = lock_value.borrow();
self.mid
.lock_write(lock)
.and_then(|mid_value| (self.next.set)(mid_value))
})
}
#[inline]
pub fn get_optional(&self, root: Option<Root>) -> Option<Value>
where
V: Clone,
{
root.and_then(|r| self.get(r))
}
#[inline]
pub fn get_mut_optional(&self, root: Option<MutRoot>) -> Option<MutValue> {
root.and_then(|r| self.get_mut(r))
}
#[inline]
pub fn get_or_else<F>(&self, root: Option<Root>, f: F) -> Value
where
V: Clone,
F: FnOnce() -> Value,
{
self.get_optional(root).unwrap_or_else(f)
}
#[inline]
pub fn get_mut_or_else<F>(&self, root: Option<MutRoot>, f: F) -> MutValue
where
F: FnOnce() -> MutValue,
{
self.get_mut_optional(root).unwrap_or_else(f)
}
pub fn set<F>(&self, root: Root, updater: F) -> Result<(), String>
where
F: FnOnce(&mut V),
MutValue: std::borrow::BorrowMut<V>,
{
(self.prev.get)(root)
.ok_or_else(|| "Failed to get lock container".to_string())
.and_then(|lock_value| {
let lock: &Lock = lock_value.borrow();
self.mid
.lock_write(lock)
.ok_or_else(|| "Failed to lock".to_string())
.and_then(|mid_value| {
(self.next.set)(mid_value)
.ok_or_else(|| "Failed to get value".to_string())
.map(|mut value| {
updater(value.borrow_mut());
})
})
})
}
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: std::borrow::Borrow<V>,
Value2: std::borrow::Borrow<V2>,
MutValue: std::borrow::BorrowMut<V>,
MutValue2: std::borrow::BorrowMut<V2>,
G3: Fn(Value) -> Option<Value2> + 'static,
S3: Fn(MutValue) -> Option<MutValue2> + 'static,
{
let next_get = self.next.get;
let next_set = self.next.set;
let chained_kp = Kp::new(
move |mid_value: MidValue| next_get(mid_value).and_then(|v| (next_kp.get)(v)),
move |mid_value: MutMid| next_set(mid_value).and_then(|v| (next_kp.set)(v)),
);
LockKp::new(self.prev, self.mid, chained_kp)
}
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: std::borrow::Borrow<V>,
LockValue2: std::borrow::Borrow<Lock2>,
MidValue2: std::borrow::Borrow<Mid2>,
Value2: std::borrow::Borrow<V2>,
MutValue: std::borrow::BorrowMut<V>,
MutLock2: std::borrow::BorrowMut<Lock2>,
MutMid2: std::borrow::BorrowMut<Mid2>,
MutValue2: std::borrow::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,
{
let next_get = self.next.get;
let next_set = self.next.set;
let other_prev_get = other.prev.get;
let other_prev_set = other.prev.set;
let other_mid1 = other.mid.clone();
let other_mid2 = other.mid;
let other_next_get = other.next.get;
let other_next_set = other.next.set;
let composed_kp = Kp::new(
move |mid_value: MidValue| {
next_get(mid_value).and_then(|value1| {
other_prev_get(value1).and_then(|lock2_value| {
let lock2: &Lock2 = lock2_value.borrow();
other_mid1.lock_read(lock2).and_then(|mid2_value| {
other_next_get(mid2_value)
})
})
})
},
move |mid_value: MutMid| {
next_set(mid_value).and_then(|value1| {
other_prev_set(value1).and_then(|lock2_value| {
let lock2: &Lock2 = lock2_value.borrow();
other_mid2
.lock_write(lock2)
.and_then(|mid2_value| other_next_set(mid2_value))
})
})
},
);
LockKp::new(self.prev, self.mid, composed_kp)
}
pub fn then_async<AsyncKp>(
self,
async_kp: AsyncKp,
) -> crate::async_lock::KpThenAsyncKeyPath<
R,
V,
<AsyncKp::Value as crate::KeyPathValueTarget>::Target,
Root,
Value,
AsyncKp::Value,
MutRoot,
MutValue,
AsyncKp::MutValue,
Self,
AsyncKp,
>
where
V: 'static + Clone,
Value: std::borrow::Borrow<V>,
MutValue: std::borrow::BorrowMut<V>,
AsyncKp: crate::async_lock::AsyncKeyPathLike<Value, MutValue>,
AsyncKp::Value: crate::KeyPathValueTarget
+ std::borrow::Borrow<<AsyncKp::Value as crate::KeyPathValueTarget>::Target>,
AsyncKp::MutValue:
std::borrow::BorrowMut<<AsyncKp::Value as crate::KeyPathValueTarget>::Target>,
<AsyncKp::Value as crate::KeyPathValueTarget>::Target: 'static,
{
crate::async_lock::KpThenAsyncKeyPath {
first: self,
second: async_kp,
_p: std::marker::PhantomData,
}
}
}
#[derive(Clone)]
pub struct KpThenLockKp<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
{
pub(crate) first: First,
pub(crate) second: Second,
pub(crate) _p:
std::marker::PhantomData<(R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2)>,
}
impl<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second> fmt::Debug
for KpThenLockKp<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("KpThenLockKp")
.field("root_ty", &std::any::type_name::<R>())
.field("via_ty", &std::any::type_name::<V>())
.field("value_ty", &std::any::type_name::<V2>())
.finish_non_exhaustive()
}
}
impl<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second> fmt::Display
for KpThenLockKp<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"KpThenLockKp<{}, {}, {}>",
std::any::type_name::<R>(),
std::any::type_name::<V>(),
std::any::type_name::<V2>()
)
}
}
impl<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
KpThenLockKp<R, V, V2, Root, Value, Value2, MutRoot, MutValue, MutValue2, First, Second>
where
First: crate::async_lock::SyncKeyPathLike<Root, Value, MutRoot, MutValue>,
Second: crate::async_lock::SyncKeyPathLike<Value, Value2, MutValue, MutValue2>,
{
#[inline]
pub fn get(&self, root: Root) -> Option<Value2>
where
Value2: Clone,
{
let v = self.first.sync_get(root)?;
self.second.sync_get(v)
}
#[inline]
pub fn get_mut(&self, root: MutRoot) -> Option<MutValue2> {
let mut_v = self.first.sync_get_mut(root)?;
self.second.sync_get_mut(mut_v)
}
#[inline]
pub fn get_optional(&self, root: Option<Root>) -> Option<Value2>
where
Value2: Clone,
{
root.and_then(|r| self.get(r))
}
#[inline]
pub fn get_mut_optional(&self, root: Option<MutRoot>) -> Option<MutValue2> {
root.and_then(|r| self.get_mut(r))
}
#[inline]
pub fn get_or_else<F>(&self, root: Option<Root>, f: F) -> Value2
where
Value2: Clone,
F: FnOnce() -> Value2,
{
self.get_optional(root).unwrap_or_else(f)
}
#[inline]
pub fn get_mut_or_else<F>(&self, root: Option<MutRoot>, f: F) -> MutValue2
where
F: FnOnce() -> MutValue2,
{
self.get_mut_optional(root).unwrap_or_else(f)
}
}
#[derive(Clone)] pub struct ArcMutexAccess<T> {
_phantom: std::marker::PhantomData<T>, }
impl<T> ArcMutexAccess<T> {
pub fn new() -> Self {
Self {
_phantom: std::marker::PhantomData,
}
}
}
impl<T> Default for ArcMutexAccess<T> {
fn default() -> Self {
Self::new()
}
}
impl<'a, T: 'static> LockAccess<Arc<Mutex<T>>, &'a T> for ArcMutexAccess<T> {
#[inline]
fn lock_read(&self, lock: &Arc<Mutex<T>>) -> Option<&'a T> {
lock.lock().ok().map(|guard| {
let ptr = &*guard as *const T;
unsafe { &*ptr }
})
}
#[inline]
fn lock_write(&self, lock: &Arc<Mutex<T>>) -> Option<&'a T> {
lock.lock().ok().map(|guard| {
let ptr = &*guard as *const T;
unsafe { &*ptr }
})
}
}
impl<'a, T: 'static> LockAccess<Arc<Mutex<T>>, &'a mut T> for ArcMutexAccess<T> {
#[inline]
fn lock_read(&self, lock: &Arc<Mutex<T>>) -> Option<&'a mut T> {
lock.lock().ok().map(|mut guard| {
let ptr = &mut *guard as *mut T;
unsafe { &mut *ptr }
})
}
#[inline]
fn lock_write(&self, lock: &Arc<Mutex<T>>) -> Option<&'a mut T> {
lock.lock().ok().map(|mut guard| {
let ptr = &mut *guard as *mut T;
unsafe { &mut *ptr }
})
}
}
#[derive(Clone)] pub struct ArcRwLockAccess<T> {
_phantom: std::marker::PhantomData<T>, }
impl<T> ArcRwLockAccess<T> {
pub fn new() -> Self {
Self {
_phantom: std::marker::PhantomData,
}
}
}
impl<T> Default for ArcRwLockAccess<T> {
fn default() -> Self {
Self::new()
}
}
impl<'a, T: 'static> LockAccess<Arc<std::sync::RwLock<T>>, &'a T> for ArcRwLockAccess<T> {
fn lock_read(&self, lock: &Arc<std::sync::RwLock<T>>) -> Option<&'a T> {
lock.read().ok().map(|guard| {
let ptr = &*guard as *const T;
unsafe { &*ptr }
})
}
fn lock_write(&self, lock: &Arc<std::sync::RwLock<T>>) -> Option<&'a T> {
lock.read().ok().map(|guard| {
let ptr = &*guard as *const T;
unsafe { &*ptr }
})
}
}
impl<'a, T: 'static> LockAccess<Arc<std::sync::RwLock<T>>, &'a mut T> for ArcRwLockAccess<T> {
fn lock_read(&self, lock: &Arc<std::sync::RwLock<T>>) -> Option<&'a mut T> {
lock.write().ok().map(|mut guard| {
let ptr = &mut *guard as *mut T;
unsafe { &mut *ptr }
})
}
fn lock_write(&self, lock: &Arc<std::sync::RwLock<T>>) -> Option<&'a mut T> {
lock.write().ok().map(|mut guard| {
let ptr = &mut *guard as *mut T;
unsafe { &mut *ptr }
})
}
}
#[derive(Clone)]
pub struct StdMutexAccess<T> {
_phantom: std::marker::PhantomData<T>,
}
impl<T> StdMutexAccess<T> {
pub fn new() -> Self {
Self {
_phantom: std::marker::PhantomData,
}
}
}
impl<T> Default for StdMutexAccess<T> {
fn default() -> Self {
Self::new()
}
}
impl<'a, T: 'static> LockAccess<Mutex<T>, &'a T> for StdMutexAccess<T> {
fn lock_read(&self, lock: &Mutex<T>) -> Option<&'a T> {
lock.lock().ok().map(|guard| {
let ptr = &*guard as *const T;
unsafe { &*ptr }
})
}
fn lock_write(&self, lock: &Mutex<T>) -> Option<&'a T> {
lock.lock().ok().map(|guard| {
let ptr = &*guard as *const T;
unsafe { &*ptr }
})
}
}
impl<'a, T: 'static> LockAccess<Mutex<T>, &'a mut T> for StdMutexAccess<T> {
fn lock_read(&self, lock: &Mutex<T>) -> Option<&'a mut T> {
lock.lock().ok().map(|mut guard| {
let ptr = &mut *guard as *mut T;
unsafe { &mut *ptr }
})
}
fn lock_write(&self, lock: &Mutex<T>) -> Option<&'a mut T> {
lock.lock().ok().map(|mut guard| {
let ptr = &mut *guard as *mut T;
unsafe { &mut *ptr }
})
}
}
#[derive(Clone)]
pub struct StdRwLockAccess<T> {
_phantom: std::marker::PhantomData<T>,
}
impl<T> StdRwLockAccess<T> {
pub fn new() -> Self {
Self {
_phantom: std::marker::PhantomData,
}
}
}
impl<T> Default for StdRwLockAccess<T> {
fn default() -> Self {
Self::new()
}
}
impl<'a, T: 'static> LockAccess<std::sync::RwLock<T>, &'a T> for StdRwLockAccess<T> {
fn lock_read(&self, lock: &std::sync::RwLock<T>) -> Option<&'a T> {
lock.read().ok().map(|guard| {
let ptr = &*guard as *const T;
unsafe { &*ptr }
})
}
fn lock_write(&self, lock: &std::sync::RwLock<T>) -> Option<&'a T> {
lock.read().ok().map(|guard| {
let ptr = &*guard as *const T;
unsafe { &*ptr }
})
}
}
impl<'a, T: 'static> LockAccess<std::sync::RwLock<T>, &'a mut T> for StdRwLockAccess<T> {
fn lock_read(&self, lock: &std::sync::RwLock<T>) -> Option<&'a mut T> {
lock.write().ok().map(|mut guard| {
let ptr = &mut *guard as *mut T;
unsafe { &mut *ptr }
})
}
fn lock_write(&self, lock: &std::sync::RwLock<T>) -> Option<&'a mut T> {
lock.write().ok().map(|mut guard| {
let ptr = &mut *guard as *mut T;
unsafe { &mut *ptr }
})
}
}
#[cfg(feature = "parking_lot")]
#[derive(Clone)] pub struct ParkingLotMutexAccess<T> {
_phantom: std::marker::PhantomData<T>,
}
#[cfg(feature = "parking_lot")]
impl<T> ParkingLotMutexAccess<T> {
pub fn new() -> Self {
Self {
_phantom: std::marker::PhantomData,
}
}
}
#[cfg(feature = "parking_lot")]
impl<T> Default for ParkingLotMutexAccess<T> {
fn default() -> Self {
Self::new()
}
}
#[cfg(feature = "parking_lot")]
impl<'a, T: 'static> LockAccess<Arc<parking_lot::Mutex<T>>, &'a T> for ParkingLotMutexAccess<T> {
fn lock_read(&self, lock: &Arc<parking_lot::Mutex<T>>) -> Option<&'a T> {
let guard = lock.lock();
let ptr = &*guard as *const T;
unsafe { Some(&*ptr) }
}
fn lock_write(&self, lock: &Arc<parking_lot::Mutex<T>>) -> Option<&'a T> {
let guard = lock.lock();
let ptr = &*guard as *const T;
unsafe { Some(&*ptr) }
}
}
#[cfg(feature = "parking_lot")]
impl<'a, T: 'static> LockAccess<Arc<parking_lot::Mutex<T>>, &'a mut T>
for ParkingLotMutexAccess<T>
{
fn lock_read(&self, lock: &Arc<parking_lot::Mutex<T>>) -> Option<&'a mut T> {
let mut guard = lock.lock();
let ptr = &mut *guard as *mut T;
unsafe { Some(&mut *ptr) }
}
fn lock_write(&self, lock: &Arc<parking_lot::Mutex<T>>) -> Option<&'a mut T> {
let mut guard = lock.lock();
let ptr = &mut *guard as *mut T;
unsafe { Some(&mut *ptr) }
}
}
#[cfg(feature = "parking_lot")]
#[derive(Clone)] pub struct ParkingLotRwLockAccess<T> {
_phantom: std::marker::PhantomData<T>,
}
#[cfg(feature = "parking_lot")]
impl<T> ParkingLotRwLockAccess<T> {
pub fn new() -> Self {
Self {
_phantom: std::marker::PhantomData,
}
}
}
#[cfg(feature = "parking_lot")]
impl<T> Default for ParkingLotRwLockAccess<T> {
fn default() -> Self {
Self::new()
}
}
#[cfg(feature = "parking_lot")]
impl<'a, T: 'static> LockAccess<Arc<parking_lot::RwLock<T>>, &'a T> for ParkingLotRwLockAccess<T> {
fn lock_read(&self, lock: &Arc<parking_lot::RwLock<T>>) -> Option<&'a T> {
let guard = lock.read();
let ptr = &*guard as *const T;
unsafe { Some(&*ptr) }
}
fn lock_write(&self, lock: &Arc<parking_lot::RwLock<T>>) -> Option<&'a T> {
let guard = lock.read();
let ptr = &*guard as *const T;
unsafe { Some(&*ptr) }
}
}
#[cfg(feature = "parking_lot")]
impl<'a, T: 'static> LockAccess<Arc<parking_lot::RwLock<T>>, &'a mut T>
for ParkingLotRwLockAccess<T>
{
fn lock_read(&self, lock: &Arc<parking_lot::RwLock<T>>) -> Option<&'a mut T> {
let mut guard = lock.write();
let ptr = &mut *guard as *mut T;
unsafe { Some(&mut *ptr) }
}
fn lock_write(&self, lock: &Arc<parking_lot::RwLock<T>>) -> Option<&'a mut T> {
let mut guard = lock.write();
let ptr = &mut *guard as *mut T;
unsafe { Some(&mut *ptr) }
}
}
#[cfg(feature = "parking_lot")]
#[derive(Clone)]
pub struct DirectParkingLotMutexAccess<T> {
_phantom: std::marker::PhantomData<T>,
}
#[cfg(feature = "parking_lot")]
impl<T> DirectParkingLotMutexAccess<T> {
pub fn new() -> Self {
Self {
_phantom: std::marker::PhantomData,
}
}
}
#[cfg(feature = "parking_lot")]
impl<T> Default for DirectParkingLotMutexAccess<T> {
fn default() -> Self {
Self::new()
}
}
#[cfg(feature = "parking_lot")]
impl<'a, T: 'static> LockAccess<parking_lot::Mutex<T>, &'a T> for DirectParkingLotMutexAccess<T> {
fn lock_read(&self, lock: &parking_lot::Mutex<T>) -> Option<&'a T> {
let guard = lock.lock();
let ptr = &*guard as *const T;
unsafe { Some(&*ptr) }
}
fn lock_write(&self, lock: &parking_lot::Mutex<T>) -> Option<&'a T> {
let guard = lock.lock();
let ptr = &*guard as *const T;
unsafe { Some(&*ptr) }
}
}
#[cfg(feature = "parking_lot")]
impl<'a, T: 'static> LockAccess<parking_lot::Mutex<T>, &'a mut T>
for DirectParkingLotMutexAccess<T>
{
fn lock_read(&self, lock: &parking_lot::Mutex<T>) -> Option<&'a mut T> {
let mut guard = lock.lock();
let ptr = &mut *guard as *mut T;
unsafe { Some(&mut *ptr) }
}
fn lock_write(&self, lock: &parking_lot::Mutex<T>) -> Option<&'a mut T> {
let mut guard = lock.lock();
let ptr = &mut *guard as *mut T;
unsafe { Some(&mut *ptr) }
}
}
#[cfg(feature = "parking_lot")]
#[derive(Clone)]
pub struct DirectParkingLotRwLockAccess<T> {
_phantom: std::marker::PhantomData<T>,
}
#[cfg(feature = "parking_lot")]
impl<T> DirectParkingLotRwLockAccess<T> {
pub fn new() -> Self {
Self {
_phantom: std::marker::PhantomData,
}
}
}
#[cfg(feature = "parking_lot")]
impl<T> Default for DirectParkingLotRwLockAccess<T> {
fn default() -> Self {
Self::new()
}
}
#[cfg(feature = "parking_lot")]
impl<'a, T: 'static> LockAccess<parking_lot::RwLock<T>, &'a T> for DirectParkingLotRwLockAccess<T> {
fn lock_read(&self, lock: &parking_lot::RwLock<T>) -> Option<&'a T> {
let guard = lock.read();
let ptr = &*guard as *const T;
unsafe { Some(&*ptr) }
}
fn lock_write(&self, lock: &parking_lot::RwLock<T>) -> Option<&'a T> {
let guard = lock.read();
let ptr = &*guard as *const T;
unsafe { Some(&*ptr) }
}
}
#[cfg(feature = "parking_lot")]
impl<'a, T: 'static> LockAccess<parking_lot::RwLock<T>, &'a mut T>
for DirectParkingLotRwLockAccess<T>
{
fn lock_read(&self, lock: &parking_lot::RwLock<T>) -> Option<&'a mut T> {
let mut guard = lock.write();
let ptr = &mut *guard as *mut T;
unsafe { Some(&mut *ptr) }
}
fn lock_write(&self, lock: &parking_lot::RwLock<T>) -> Option<&'a mut T> {
let mut guard = lock.write();
let ptr = &mut *guard as *mut T;
unsafe { Some(&mut *ptr) }
}
}
#[derive(Clone)] pub struct RcRefCellAccess<T> {
_phantom: std::marker::PhantomData<T>, }
impl<T> RcRefCellAccess<T> {
pub fn new() -> Self {
Self {
_phantom: std::marker::PhantomData,
}
}
}
impl<T> Default for RcRefCellAccess<T> {
fn default() -> Self {
Self::new()
}
}
impl<'a, T: 'static> LockAccess<std::rc::Rc<std::cell::RefCell<T>>, &'a T> for RcRefCellAccess<T> {
fn lock_read(&self, lock: &std::rc::Rc<std::cell::RefCell<T>>) -> Option<&'a T> {
let guard = lock.borrow();
let ptr = &*guard as *const T;
unsafe { Some(&*ptr) }
}
fn lock_write(&self, lock: &std::rc::Rc<std::cell::RefCell<T>>) -> Option<&'a T> {
let guard = lock.borrow();
let ptr = &*guard as *const T;
unsafe { Some(&*ptr) }
}
}
impl<'a, T: 'static> LockAccess<std::rc::Rc<std::cell::RefCell<T>>, &'a mut T>
for RcRefCellAccess<T>
{
fn lock_read(&self, lock: &std::rc::Rc<std::cell::RefCell<T>>) -> Option<&'a mut T> {
let mut guard = lock.borrow_mut();
let ptr = &mut *guard as *mut T;
unsafe { Some(&mut *ptr) }
}
fn lock_write(&self, lock: &std::rc::Rc<std::cell::RefCell<T>>) -> Option<&'a mut T> {
let mut guard = lock.borrow_mut();
let ptr = &mut *guard as *mut T;
unsafe { Some(&mut *ptr) }
}
}
pub type LockKpArcMutexFor<Root, Lock, Inner> = LockKp<
Root,
Lock,
Inner,
Inner,
&'static Root,
&'static Lock,
&'static Inner,
&'static Inner,
&'static mut Root,
&'static mut Lock,
&'static mut Inner,
&'static mut Inner,
for<'b> fn(&'b Root) -> Option<&'b Lock>,
for<'b> fn(&'b mut Root) -> Option<&'b mut Lock>,
ArcMutexAccess<Inner>,
for<'b> fn(&'b Inner) -> Option<&'b Inner>,
for<'b> fn(&'b mut Inner) -> Option<&'b mut Inner>,
>;
pub type LockKpArcMutexOptionFor<Root, Lock, Inner> = LockKp<
Root,
Lock,
Option<Inner>,
Inner,
&'static Root,
&'static Lock,
&'static Option<Inner>,
&'static Inner,
&'static mut Root,
&'static mut Lock,
&'static mut Option<Inner>,
&'static mut Inner,
for<'b> fn(&'b Root) -> Option<&'b Lock>,
for<'b> fn(&'b mut Root) -> Option<&'b mut Lock>,
ArcMutexAccess<Option<Inner>>,
for<'b> fn(&'b Option<Inner>) -> Option<&'b Inner>,
for<'b> fn(&'b mut Option<Inner>) -> Option<&'b mut Inner>,
>;
pub type LockKpArcRwLockFor<Root, Lock, Inner> = LockKp<
Root,
Lock,
Inner,
Inner,
&'static Root,
&'static Lock,
&'static Inner,
&'static Inner,
&'static mut Root,
&'static mut Lock,
&'static mut Inner,
&'static mut Inner,
for<'b> fn(&'b Root) -> Option<&'b Lock>,
for<'b> fn(&'b mut Root) -> Option<&'b mut Lock>,
ArcRwLockAccess<Inner>,
for<'b> fn(&'b Inner) -> Option<&'b Inner>,
for<'b> fn(&'b mut Inner) -> Option<&'b mut Inner>,
>;
pub type LockKpArcRwLockOptionFor<Root, Lock, Inner> = LockKp<
Root,
Lock,
Option<Inner>,
Inner,
&'static Root,
&'static Lock,
&'static Option<Inner>,
&'static Inner,
&'static mut Root,
&'static mut Lock,
&'static mut Option<Inner>,
&'static mut Inner,
for<'b> fn(&'b Root) -> Option<&'b Lock>,
for<'b> fn(&'b mut Root) -> Option<&'b mut Lock>,
ArcRwLockAccess<Option<Inner>>,
for<'b> fn(&'b Option<Inner>) -> Option<&'b Inner>,
for<'b> fn(&'b mut Option<Inner>) -> Option<&'b mut Inner>,
>;
#[cfg(feature = "parking_lot")]
pub type LockKpParkingLotMutexFor<Root, Lock, Inner> = LockKp<
Root,
Lock,
Inner,
Inner,
&'static Root,
&'static Lock,
&'static Inner,
&'static Inner,
&'static mut Root,
&'static mut Lock,
&'static mut Inner,
&'static mut Inner,
for<'b> fn(&'b Root) -> Option<&'b Lock>,
for<'b> fn(&'b mut Root) -> Option<&'b mut Lock>,
ParkingLotMutexAccess<Inner>,
for<'b> fn(&'b Inner) -> Option<&'b Inner>,
for<'b> fn(&'b mut Inner) -> Option<&'b mut Inner>,
>;
#[cfg(feature = "parking_lot")]
pub type LockKpParkingLotMutexOptionFor<Root, Lock, Inner> = LockKp<
Root,
Lock,
Option<Inner>,
Inner,
&'static Root,
&'static Lock,
&'static Option<Inner>,
&'static Inner,
&'static mut Root,
&'static mut Lock,
&'static mut Option<Inner>,
&'static mut Inner,
for<'b> fn(&'b Root) -> Option<&'b Lock>,
for<'b> fn(&'b mut Root) -> Option<&'b mut Lock>,
ParkingLotMutexAccess<Option<Inner>>,
for<'b> fn(&'b Option<Inner>) -> Option<&'b Inner>,
for<'b> fn(&'b mut Option<Inner>) -> Option<&'b mut Inner>,
>;
#[cfg(feature = "parking_lot")]
pub type LockKpParkingLotRwLockFor<Root, Lock, Inner> = LockKp<
Root,
Lock,
Inner,
Inner,
&'static Root,
&'static Lock,
&'static Inner,
&'static Inner,
&'static mut Root,
&'static mut Lock,
&'static mut Inner,
&'static mut Inner,
for<'b> fn(&'b Root) -> Option<&'b Lock>,
for<'b> fn(&'b mut Root) -> Option<&'b mut Lock>,
ParkingLotRwLockAccess<Inner>,
for<'b> fn(&'b Inner) -> Option<&'b Inner>,
for<'b> fn(&'b mut Inner) -> Option<&'b mut Inner>,
>;
#[cfg(feature = "parking_lot")]
pub type LockKpParkingLotRwLockOptionFor<Root, Lock, Inner> = LockKp<
Root,
Lock,
Option<Inner>,
Inner,
&'static Root,
&'static Lock,
&'static Option<Inner>,
&'static Inner,
&'static mut Root,
&'static mut Lock,
&'static mut Option<Inner>,
&'static mut Inner,
for<'b> fn(&'b Root) -> Option<&'b Lock>,
for<'b> fn(&'b mut Root) -> Option<&'b mut Lock>,
ParkingLotRwLockAccess<Option<Inner>>,
for<'b> fn(&'b Option<Inner>) -> Option<&'b Inner>,
for<'b> fn(&'b mut Option<Inner>) -> Option<&'b mut Inner>,
>;
pub type LockKpType<'a, R, Mid, V> = LockKp<
R,
Arc<Mutex<Mid>>,
Mid,
V,
&'a R,
&'a Arc<Mutex<Mid>>,
&'a Mid,
&'a V,
&'a mut R,
&'a mut Arc<Mutex<Mid>>,
&'a mut Mid,
&'a mut V,
for<'b> fn(&'b R) -> Option<&'b Arc<Mutex<Mid>>>,
for<'b> fn(&'b mut R) -> Option<&'b mut Arc<Mutex<Mid>>>,
ArcMutexAccess<Mid>,
for<'b> fn(&'b Mid) -> Option<&'b V>,
for<'b> fn(&'b mut Mid) -> Option<&'b mut V>,
>;
#[cfg(test)]
mod tests {
use super::*;
use crate::KpType;
#[test]
fn test_lock_kp_basic() {
#[derive(Debug, Clone)]
struct Root {
locked_data: Arc<Mutex<Inner>>,
}
#[derive(Debug, Clone)]
struct Inner {
value: String,
}
let root = Root {
locked_data: Arc::new(Mutex::new(Inner {
value: "hello".to_string(),
})),
};
let prev_kp: KpType<Root, Arc<Mutex<Inner>>> = Kp::new(
|r: &Root| Some(&r.locked_data),
|r: &mut Root| Some(&mut r.locked_data),
);
let next_kp: KpType<Inner, String> = Kp::new(
|i: &Inner| Some(&i.value),
|i: &mut Inner| Some(&mut i.value),
);
let lock_kp = LockKp::new(prev_kp, ArcMutexAccess::new(), next_kp);
let value = lock_kp.get(&root);
assert!(value.is_some());
}
#[test]
fn test_lock_kp_get_optional_or_else() {
#[derive(Debug, Clone)]
struct Root {
locked_data: Arc<Mutex<Inner>>,
}
#[derive(Debug, Clone)]
struct Inner {
value: i32,
}
let mut root = Root {
locked_data: Arc::new(Mutex::new(Inner { value: 42 })),
};
let prev_kp: KpType<Root, Arc<Mutex<Inner>>> = Kp::new(
|r: &Root| Some(&r.locked_data),
|r: &mut Root| Some(&mut r.locked_data),
);
let next_kp: KpType<Inner, i32> = Kp::new(
|i: &Inner| Some(&i.value),
|i: &mut Inner| Some(&mut i.value),
);
let lock_kp = LockKp::new(prev_kp, ArcMutexAccess::new(), next_kp);
assert!(lock_kp.get_optional(None).is_none());
assert_eq!(lock_kp.get_optional(Some(&root)), Some(&42));
assert!(lock_kp.get_mut_optional(None).is_none());
if let Some(m) = lock_kp.get_mut_optional(Some(&mut root)) {
*m = 99;
}
assert_eq!(lock_kp.get(&root), Some(&99));
static DEFAULT: i32 = -1;
let fallback = || &DEFAULT;
assert_eq!(*lock_kp.get_or_else(None, fallback), -1);
assert_eq!(*lock_kp.get_or_else(Some(&root), fallback), 99);
let m_some = lock_kp.get_mut_or_else(Some(&mut root), || panic!("should not use fallback"));
*m_some = 100;
assert_eq!(lock_kp.get(&root), Some(&100));
}
#[test]
fn test_kp_then_lock_kp_get_optional_or_else() {
#[derive(Debug, Clone)]
struct Root {
data: Arc<Mutex<Mid>>,
}
#[derive(Debug, Clone)]
struct Mid {
value: i32,
}
let _root = Root {
data: Arc::new(Mutex::new(Mid { value: 10 })),
};
let prev: KpType<Root, Arc<Mutex<Mid>>> =
Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let next: KpType<Mid, i32> =
Kp::new(|m: &Mid| Some(&m.value), |m: &mut Mid| Some(&mut m.value));
let lock_kp = LockKp::new(prev, ArcMutexAccess::new(), next);
assert!(lock_kp.get_optional(None).is_none());
assert_eq!(lock_kp.get_optional(Some(&_root)), Some(&10));
static DEF: i32 = -1;
assert_eq!(*lock_kp.get_or_else(None, || &DEF), -1);
assert_eq!(*lock_kp.get_or_else(Some(&_root), || &DEF), 10);
}
#[test]
fn test_lock_kp_structure() {
#[derive(Debug, Clone)]
struct Root {
data: Arc<Mutex<Mid>>,
}
#[derive(Debug, Clone)]
struct Mid {
value: i32,
}
let prev: KpType<Root, Arc<Mutex<Mid>>> =
Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let mid = ArcMutexAccess::<Mid>::new();
let next: KpType<Mid, i32> =
Kp::new(|m: &Mid| Some(&m.value), |m: &mut Mid| Some(&mut m.value));
let lock_kp = LockKp::new(prev, mid, next);
let _prev_field = &lock_kp.prev;
let _mid_field = &lock_kp.mid;
let _next_field = &lock_kp.next;
}
#[test]
fn test_lock_kp_then_chaining() {
#[derive(Debug, Clone)]
struct Root {
data: Arc<Mutex<Mid>>,
}
#[derive(Debug, Clone)]
struct Mid {
inner: Inner2,
}
#[derive(Debug, Clone)]
struct Inner2 {
value: String,
}
let root = Root {
data: Arc::new(Mutex::new(Mid {
inner: Inner2 {
value: "chained".to_string(),
},
})),
};
let prev: KpType<Root, Arc<Mutex<Mid>>> =
Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let to_inner: KpType<Mid, Inner2> =
Kp::new(|m: &Mid| Some(&m.inner), |m: &mut Mid| Some(&mut m.inner));
let to_value: KpType<Inner2, String> = Kp::new(
|i: &Inner2| Some(&i.value),
|i: &mut Inner2| Some(&mut i.value),
);
let lock_kp = LockKp::new(prev, ArcMutexAccess::new(), to_inner);
let chained = lock_kp.then(to_value);
let _result = chained;
}
#[test]
fn test_lock_kp_compose_single_level() {
#[derive(Debug, Clone)]
struct Root {
data: Arc<Mutex<Mid1>>,
}
#[derive(Debug, Clone)]
struct Mid1 {
nested: Arc<Mutex<Mid2>>,
}
#[derive(Debug, Clone)]
struct Mid2 {
value: String,
}
let root = Root {
data: Arc::new(Mutex::new(Mid1 {
nested: Arc::new(Mutex::new(Mid2 {
value: "nested-lock".to_string(),
})),
})),
};
let lock_kp1 = {
let prev: KpType<Root, Arc<Mutex<Mid1>>> =
Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let next: KpType<Mid1, Mid1> = Kp::new(|m: &Mid1| Some(m), |m: &mut Mid1| Some(m));
LockKp::new(prev, ArcMutexAccess::new(), next)
};
let lock_kp2 = {
let prev: KpType<Mid1, Arc<Mutex<Mid2>>> = Kp::new(
|m: &Mid1| Some(&m.nested),
|m: &mut Mid1| Some(&mut m.nested),
);
let next: KpType<Mid2, String> =
Kp::new(|m: &Mid2| Some(&m.value), |m: &mut Mid2| Some(&mut m.value));
LockKp::new(prev, ArcMutexAccess::new(), next)
};
let composed = lock_kp1.then_lock(lock_kp2);
let value = composed.get(&root);
assert!(value.is_some());
}
#[test]
fn test_lock_kp_compose_two_levels() {
#[derive(Debug, Clone)]
struct Root {
level1: Arc<Mutex<Level1>>,
}
#[derive(Debug, Clone)]
struct Level1 {
data: String,
level2: Arc<Mutex<Level2>>,
}
#[derive(Debug, Clone)]
struct Level2 {
value: i32,
}
let root = Root {
level1: Arc::new(Mutex::new(Level1 {
data: "level1".to_string(),
level2: Arc::new(Mutex::new(Level2 { value: 42 })),
})),
};
let lock1 = {
let prev: KpType<Root, Arc<Mutex<Level1>>> = Kp::new(
|r: &Root| Some(&r.level1),
|r: &mut Root| Some(&mut r.level1),
);
let next: KpType<Level1, Level1> =
Kp::new(|l: &Level1| Some(l), |l: &mut Level1| Some(l));
LockKp::new(prev, ArcMutexAccess::new(), next)
};
let lock2 = {
let prev: KpType<Level1, Arc<Mutex<Level2>>> = Kp::new(
|l: &Level1| Some(&l.level2),
|l: &mut Level1| Some(&mut l.level2),
);
let next: KpType<Level2, i32> = Kp::new(
|l: &Level2| Some(&l.value),
|l: &mut Level2| Some(&mut l.value),
);
LockKp::new(prev, ArcMutexAccess::new(), next)
};
let composed = lock1.then_lock(lock2);
let value = composed.get(&root);
assert!(value.is_some());
}
#[test]
fn test_lock_kp_compose_three_levels() {
#[derive(Debug, Clone)]
struct Root {
lock1: Arc<Mutex<L1>>,
}
#[derive(Debug, Clone)]
struct L1 {
lock2: Arc<Mutex<L2>>,
}
#[derive(Debug, Clone)]
struct L2 {
lock3: Arc<Mutex<L3>>,
}
#[derive(Debug, Clone)]
struct L3 {
final_value: String,
}
let root = Root {
lock1: Arc::new(Mutex::new(L1 {
lock2: Arc::new(Mutex::new(L2 {
lock3: Arc::new(Mutex::new(L3 {
final_value: "deeply-nested".to_string(),
})),
})),
})),
};
let lock_kp1 = {
let prev: KpType<Root, Arc<Mutex<L1>>> =
Kp::new(|r: &Root| Some(&r.lock1), |r: &mut Root| Some(&mut r.lock1));
let next: KpType<L1, L1> = Kp::new(|l: &L1| Some(l), |l: &mut L1| Some(l));
LockKp::new(prev, ArcMutexAccess::new(), next)
};
let lock_kp2 = {
let prev: KpType<L1, Arc<Mutex<L2>>> =
Kp::new(|l: &L1| Some(&l.lock2), |l: &mut L1| Some(&mut l.lock2));
let next: KpType<L2, L2> = Kp::new(|l: &L2| Some(l), |l: &mut L2| Some(l));
LockKp::new(prev, ArcMutexAccess::new(), next)
};
let lock_kp3 = {
let prev: KpType<L2, Arc<Mutex<L3>>> =
Kp::new(|l: &L2| Some(&l.lock3), |l: &mut L2| Some(&mut l.lock3));
let next: KpType<L3, String> = Kp::new(
|l: &L3| Some(&l.final_value),
|l: &mut L3| Some(&mut l.final_value),
);
LockKp::new(prev, ArcMutexAccess::new(), next)
};
let composed_1_2 = lock_kp1.then_lock(lock_kp2);
let composed_all = composed_1_2.then_lock(lock_kp3);
let value = composed_all.get(&root);
assert!(value.is_some());
}
#[test]
fn test_lock_kp_compose_with_then() {
#[derive(Debug, Clone)]
struct Root {
lock1: Arc<Mutex<Mid>>,
}
#[derive(Debug, Clone)]
struct Mid {
lock2: Arc<Mutex<Inner>>,
}
#[derive(Debug, Clone)]
struct Inner {
data: Data,
}
#[derive(Debug, Clone)]
struct Data {
value: i32,
}
let root = Root {
lock1: Arc::new(Mutex::new(Mid {
lock2: Arc::new(Mutex::new(Inner {
data: Data { value: 100 },
})),
})),
};
let lock1 = {
let prev: KpType<Root, Arc<Mutex<Mid>>> =
Kp::new(|r: &Root| Some(&r.lock1), |r: &mut Root| Some(&mut r.lock1));
let next: KpType<Mid, Mid> = Kp::new(|m: &Mid| Some(m), |m: &mut Mid| Some(m));
LockKp::new(prev, ArcMutexAccess::new(), next)
};
let lock2 = {
let prev: KpType<Mid, Arc<Mutex<Inner>>> =
Kp::new(|m: &Mid| Some(&m.lock2), |m: &mut Mid| Some(&mut m.lock2));
let next: KpType<Inner, Inner> = Kp::new(|i: &Inner| Some(i), |i: &mut Inner| Some(i));
LockKp::new(prev, ArcMutexAccess::new(), next)
};
let to_data: KpType<Inner, Data> =
Kp::new(|i: &Inner| Some(&i.data), |i: &mut Inner| Some(&mut i.data));
let to_value: KpType<Data, i32> =
Kp::new(|d: &Data| Some(&d.value), |d: &mut Data| Some(&mut d.value));
let composed = lock1.then_lock(lock2);
let with_data = composed.then(to_data);
let with_value = with_data.then(to_value);
let value = with_value.get(&root);
assert!(value.is_some());
}
#[test]
fn test_rwlock_basic() {
use std::sync::RwLock;
#[derive(Debug, Clone)]
struct Root {
data: Arc<RwLock<Inner>>,
}
#[derive(Debug, Clone)]
struct Inner {
value: String,
}
let root = Root {
data: Arc::new(RwLock::new(Inner {
value: "rwlock_value".to_string(),
})),
};
let prev: KpType<Root, Arc<RwLock<Inner>>> =
Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let next: KpType<Inner, String> = Kp::new(
|i: &Inner| Some(&i.value),
|i: &mut Inner| Some(&mut i.value),
);
let rwlock_kp = LockKp::new(prev, ArcRwLockAccess::new(), next);
let value = rwlock_kp.get(&root);
assert!(value.is_some());
}
#[test]
fn test_rwlock_compose_two_levels() {
use std::sync::RwLock;
#[derive(Debug, Clone)]
struct Root {
level1: Arc<RwLock<Level1>>,
}
#[derive(Debug, Clone)]
struct Level1 {
level2: Arc<RwLock<Level2>>,
}
#[derive(Debug, Clone)]
struct Level2 {
value: i32,
}
let root = Root {
level1: Arc::new(RwLock::new(Level1 {
level2: Arc::new(RwLock::new(Level2 { value: 100 })),
})),
};
let lock1 = {
let prev: KpType<Root, Arc<RwLock<Level1>>> = Kp::new(
|r: &Root| Some(&r.level1),
|r: &mut Root| Some(&mut r.level1),
);
let next: KpType<Level1, Level1> =
Kp::new(|l: &Level1| Some(l), |l: &mut Level1| Some(l));
LockKp::new(prev, ArcRwLockAccess::new(), next)
};
let lock2 = {
let prev: KpType<Level1, Arc<RwLock<Level2>>> = Kp::new(
|l: &Level1| Some(&l.level2),
|l: &mut Level1| Some(&mut l.level2),
);
let next: KpType<Level2, i32> = Kp::new(
|l: &Level2| Some(&l.value),
|l: &mut Level2| Some(&mut l.value),
);
LockKp::new(prev, ArcRwLockAccess::new(), next)
};
let composed = lock1.then_lock(lock2);
let value = composed.get(&root);
assert!(value.is_some());
}
#[test]
fn test_rwlock_mixed_with_mutex() {
use std::sync::RwLock;
#[derive(Debug, Clone)]
struct Root {
rwlock_data: Arc<RwLock<Mid>>,
}
#[derive(Debug, Clone)]
struct Mid {
mutex_data: Arc<Mutex<Inner>>,
}
#[derive(Debug, Clone)]
struct Inner {
value: String,
}
let root = Root {
rwlock_data: Arc::new(RwLock::new(Mid {
mutex_data: Arc::new(Mutex::new(Inner {
value: "mixed".to_string(),
})),
})),
};
let rwlock_kp = {
let prev: KpType<Root, Arc<RwLock<Mid>>> = Kp::new(
|r: &Root| Some(&r.rwlock_data),
|r: &mut Root| Some(&mut r.rwlock_data),
);
let next: KpType<Mid, Mid> = Kp::new(|m: &Mid| Some(m), |m: &mut Mid| Some(m));
LockKp::new(prev, ArcRwLockAccess::new(), next)
};
let mutex_kp = {
let prev: KpType<Mid, Arc<Mutex<Inner>>> = Kp::new(
|m: &Mid| Some(&m.mutex_data),
|m: &mut Mid| Some(&mut m.mutex_data),
);
let next: KpType<Inner, String> = Kp::new(
|i: &Inner| Some(&i.value),
|i: &mut Inner| Some(&mut i.value),
);
LockKp::new(prev, ArcMutexAccess::new(), next)
};
let composed = rwlock_kp.then_lock(mutex_kp);
let value = composed.get(&root);
assert!(value.is_some());
}
#[test]
fn test_rwlock_structure() {
use std::sync::RwLock;
#[derive(Debug, Clone)]
struct Root {
data: Arc<RwLock<Inner>>,
}
#[derive(Debug, Clone)]
struct Inner {
value: i32,
}
let root = Root {
data: Arc::new(RwLock::new(Inner { value: 42 })),
};
let prev: KpType<Root, Arc<RwLock<Inner>>> =
Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let mid = ArcRwLockAccess::<Inner>::new();
let next: KpType<Inner, i32> = Kp::new(
|i: &Inner| Some(&i.value),
|i: &mut Inner| Some(&mut i.value),
);
let rwlock_kp = LockKp::new(prev, mid, next);
let _prev_field = &rwlock_kp.prev;
let _mid_field = &rwlock_kp.mid;
let _next_field = &rwlock_kp.next;
let value = rwlock_kp.get(&root);
assert!(value.is_some());
}
#[test]
fn test_rwlock_three_levels() {
use std::sync::RwLock;
#[derive(Debug, Clone)]
struct Root {
lock1: Arc<RwLock<L1>>,
}
#[derive(Debug, Clone)]
struct L1 {
lock2: Arc<RwLock<L2>>,
}
#[derive(Debug, Clone)]
struct L2 {
lock3: Arc<RwLock<L3>>,
}
#[derive(Debug, Clone)]
struct L3 {
value: String,
}
let root = Root {
lock1: Arc::new(RwLock::new(L1 {
lock2: Arc::new(RwLock::new(L2 {
lock3: Arc::new(RwLock::new(L3 {
value: "deep_rwlock".to_string(),
})),
})),
})),
};
let lock1 = {
let prev: KpType<Root, Arc<RwLock<L1>>> =
Kp::new(|r: &Root| Some(&r.lock1), |r: &mut Root| Some(&mut r.lock1));
let next: KpType<L1, L1> = Kp::new(|l: &L1| Some(l), |l: &mut L1| Some(l));
LockKp::new(prev, ArcRwLockAccess::new(), next)
};
let lock2 = {
let prev: KpType<L1, Arc<RwLock<L2>>> =
Kp::new(|l: &L1| Some(&l.lock2), |l: &mut L1| Some(&mut l.lock2));
let next: KpType<L2, L2> = Kp::new(|l: &L2| Some(l), |l: &mut L2| Some(l));
LockKp::new(prev, ArcRwLockAccess::new(), next)
};
let lock3 = {
let prev: KpType<L2, Arc<RwLock<L3>>> =
Kp::new(|l: &L2| Some(&l.lock3), |l: &mut L2| Some(&mut l.lock3));
let next: KpType<L3, String> =
Kp::new(|l: &L3| Some(&l.value), |l: &mut L3| Some(&mut l.value));
LockKp::new(prev, ArcRwLockAccess::new(), next)
};
let composed = lock1.then_lock(lock2).then_lock(lock3);
let value = composed.get(&root);
assert!(value.is_some());
}
#[test]
fn test_rwlock_panic_on_clone_proof() {
use std::sync::RwLock;
struct PanicOnClone {
data: String,
}
impl PanicOnClone {
fn new(s: &str) -> Self {
Self {
data: s.to_string(),
}
}
fn get_data(&self) -> &String {
&self.data
}
}
impl Clone for PanicOnClone {
fn clone(&self) -> Self {
panic!(
"❌ DEEP CLONE DETECTED! PanicOnClone was cloned! This should NEVER happen!"
);
}
}
#[derive(Clone)]
struct Root {
lock1: Arc<RwLock<Level1>>,
}
struct Level1 {
panic_data: PanicOnClone,
lock2: Arc<RwLock<Level2>>,
}
impl Clone for Level1 {
fn clone(&self) -> Self {
panic!("❌ Level1 was deeply cloned! This should NEVER happen!");
}
}
struct Level2 {
panic_data2: PanicOnClone,
value: i32,
}
impl Clone for Level2 {
fn clone(&self) -> Self {
panic!("❌ Level2 was deeply cloned! This should NEVER happen!");
}
}
let root = Root {
lock1: Arc::new(RwLock::new(Level1 {
panic_data: PanicOnClone::new("level1_data"),
lock2: Arc::new(RwLock::new(Level2 {
panic_data2: PanicOnClone::new("level2_data"),
value: 42,
})),
})),
};
let lock1 = {
let prev: KpType<Root, Arc<RwLock<Level1>>> =
Kp::new(|r: &Root| Some(&r.lock1), |r: &mut Root| Some(&mut r.lock1));
let next: KpType<Level1, Level1> =
Kp::new(|l: &Level1| Some(l), |l: &mut Level1| Some(l));
LockKp::new(prev, ArcRwLockAccess::new(), next)
};
let lock2 = {
let prev: KpType<Level1, Arc<RwLock<Level2>>> = Kp::new(
|l: &Level1| Some(&l.lock2),
|l: &mut Level1| Some(&mut l.lock2),
);
let next: KpType<Level2, i32> = Kp::new(
|l: &Level2| Some(&l.value),
|l: &mut Level2| Some(&mut l.value),
);
LockKp::new(prev, ArcRwLockAccess::new(), next)
};
let composed = lock1.then_lock(lock2);
let value = composed.get(&root);
assert!(value.is_some());
}
#[test]
fn test_mutex_panic_on_clone_proof() {
struct PanicOnClone {
data: Vec<u8>,
}
impl PanicOnClone {
fn new(size: usize) -> Self {
Self {
data: vec![0u8; size],
}
}
}
impl Clone for PanicOnClone {
fn clone(&self) -> Self {
panic!("❌ DEEP CLONE DETECTED! PanicOnClone was cloned!");
}
}
#[derive(Clone)]
struct Root {
lock1: Arc<Mutex<Mid>>,
}
struct Mid {
panic_data: PanicOnClone,
lock2: Arc<Mutex<Inner>>,
}
impl Clone for Mid {
fn clone(&self) -> Self {
panic!("❌ Mid was deeply cloned! This should NEVER happen!");
}
}
struct Inner {
panic_data: PanicOnClone,
value: String,
}
impl Clone for Inner {
fn clone(&self) -> Self {
panic!("❌ Inner was deeply cloned! This should NEVER happen!");
}
}
let root = Root {
lock1: Arc::new(Mutex::new(Mid {
panic_data: PanicOnClone::new(1_000_000), lock2: Arc::new(Mutex::new(Inner {
panic_data: PanicOnClone::new(1_000_000), value: "test".to_string(),
})),
})),
};
let lock1 = {
let prev: KpType<Root, Arc<Mutex<Mid>>> =
Kp::new(|r: &Root| Some(&r.lock1), |r: &mut Root| Some(&mut r.lock1));
let next: KpType<Mid, Mid> = Kp::new(|m: &Mid| Some(m), |m: &mut Mid| Some(m));
LockKp::new(prev, ArcMutexAccess::new(), next)
};
let lock2 = {
let prev: KpType<Mid, Arc<Mutex<Inner>>> =
Kp::new(|m: &Mid| Some(&m.lock2), |m: &mut Mid| Some(&mut m.lock2));
let next: KpType<Inner, String> = Kp::new(
|i: &Inner| Some(&i.value),
|i: &mut Inner| Some(&mut i.value),
);
LockKp::new(prev, ArcMutexAccess::new(), next)
};
let composed = lock1.then_lock(lock2);
let value = composed.get(&root);
assert!(value.is_some());
}
#[test]
fn test_mixed_locks_panic_on_clone_proof() {
use std::sync::RwLock;
struct NeverClone {
id: usize,
large_data: Vec<u8>,
}
impl NeverClone {
fn new(id: usize) -> Self {
Self {
id,
large_data: vec![0u8; 10_000],
}
}
}
impl Clone for NeverClone {
fn clone(&self) -> Self {
panic!("❌ NeverClone with id {} was cloned!", self.id);
}
}
#[derive(Clone)]
struct Root {
rwlock: Arc<RwLock<Mid>>,
}
struct Mid {
never_clone1: NeverClone,
mutex: Arc<Mutex<Inner>>,
}
impl Clone for Mid {
fn clone(&self) -> Self {
panic!("❌ Mid was deeply cloned!");
}
}
struct Inner {
never_clone2: NeverClone,
value: i32,
}
impl Clone for Inner {
fn clone(&self) -> Self {
panic!("❌ Inner was deeply cloned!");
}
}
let root = Root {
rwlock: Arc::new(RwLock::new(Mid {
never_clone1: NeverClone::new(1),
mutex: Arc::new(Mutex::new(Inner {
never_clone2: NeverClone::new(2),
value: 999,
})),
})),
};
let rwlock_kp = {
let prev: KpType<Root, Arc<RwLock<Mid>>> = Kp::new(
|r: &Root| Some(&r.rwlock),
|r: &mut Root| Some(&mut r.rwlock),
);
let next: KpType<Mid, Mid> = Kp::new(|m: &Mid| Some(m), |m: &mut Mid| Some(m));
LockKp::new(prev, ArcRwLockAccess::new(), next)
};
let mutex_kp = {
let prev: KpType<Mid, Arc<Mutex<Inner>>> =
Kp::new(|m: &Mid| Some(&m.mutex), |m: &mut Mid| Some(&mut m.mutex));
let next: KpType<Inner, i32> = Kp::new(
|i: &Inner| Some(&i.value),
|i: &mut Inner| Some(&mut i.value),
);
LockKp::new(prev, ArcMutexAccess::new(), next)
};
let composed = rwlock_kp.then_lock(mutex_kp);
let value = composed.get(&root);
assert!(value.is_some());
let value2 = composed.get(&root);
assert!(value2.is_some());
}
#[test]
fn test_rc_refcell_basic() {
use std::cell::RefCell;
use std::rc::Rc;
#[derive(Clone)]
struct Root {
data: Rc<RefCell<Inner>>,
}
#[derive(Clone)]
struct Inner {
value: String,
}
let root = Root {
data: Rc::new(RefCell::new(Inner {
value: "hello".to_string(),
})),
};
let lock_kp = {
let prev: KpType<Root, Rc<RefCell<Inner>>> =
Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let next: KpType<Inner, String> = Kp::new(
|i: &Inner| Some(&i.value),
|i: &mut Inner| Some(&mut i.value),
);
LockKp::new(prev, RcRefCellAccess::new(), next)
};
let value = lock_kp.get(&root);
assert!(value.is_some());
assert_eq!(value.unwrap(), "hello");
let result = lock_kp.set(&root, |s| {
*s = "world".to_string();
});
assert!(result.is_ok());
let value = lock_kp.get(&root);
assert_eq!(value.unwrap(), "world");
}
#[test]
fn test_rc_refcell_compose_two_levels() {
use std::cell::RefCell;
use std::rc::Rc;
#[derive(Clone)]
struct Root {
level1: Rc<RefCell<Level1>>,
}
#[derive(Clone)]
struct Level1 {
level2: Rc<RefCell<Level2>>,
}
#[derive(Clone)]
struct Level2 {
value: i32,
}
let root = Root {
level1: Rc::new(RefCell::new(Level1 {
level2: Rc::new(RefCell::new(Level2 { value: 42 })),
})),
};
let lock1 = {
let prev: KpType<Root, Rc<RefCell<Level1>>> = Kp::new(
|r: &Root| Some(&r.level1),
|r: &mut Root| Some(&mut r.level1),
);
let next: KpType<Level1, Level1> =
Kp::new(|l: &Level1| Some(l), |l: &mut Level1| Some(l));
LockKp::new(prev, RcRefCellAccess::new(), next)
};
let lock2 = {
let prev: KpType<Level1, Rc<RefCell<Level2>>> = Kp::new(
|l: &Level1| Some(&l.level2),
|l: &mut Level1| Some(&mut l.level2),
);
let next: KpType<Level2, i32> = Kp::new(
|l: &Level2| Some(&l.value),
|l: &mut Level2| Some(&mut l.value),
);
LockKp::new(prev, RcRefCellAccess::new(), next)
};
let composed = lock1.then_lock(lock2);
let value = composed.get(&root);
assert!(value.is_some());
assert_eq!(*value.unwrap(), 42);
let result = composed.set(&root, |v| {
*v = 100;
});
assert!(result.is_ok());
let value = composed.get(&root);
assert_eq!(*value.unwrap(), 100);
}
#[test]
fn test_rc_refcell_three_levels() {
use std::cell::RefCell;
use std::rc::Rc;
#[derive(Clone)]
struct Root {
l1: Rc<RefCell<L1>>,
}
#[derive(Clone)]
struct L1 {
l2: Rc<RefCell<L2>>,
}
#[derive(Clone)]
struct L2 {
l3: Rc<RefCell<L3>>,
}
#[derive(Clone)]
struct L3 {
value: String,
}
let root = Root {
l1: Rc::new(RefCell::new(L1 {
l2: Rc::new(RefCell::new(L2 {
l3: Rc::new(RefCell::new(L3 {
value: "deep".to_string(),
})),
})),
})),
};
let lock1 = {
let prev: KpType<Root, Rc<RefCell<L1>>> =
Kp::new(|r: &Root| Some(&r.l1), |r: &mut Root| Some(&mut r.l1));
let next: KpType<L1, L1> = Kp::new(|l: &L1| Some(l), |l: &mut L1| Some(l));
LockKp::new(prev, RcRefCellAccess::new(), next)
};
let lock2 = {
let prev: KpType<L1, Rc<RefCell<L2>>> =
Kp::new(|l: &L1| Some(&l.l2), |l: &mut L1| Some(&mut l.l2));
let next: KpType<L2, L2> = Kp::new(|l: &L2| Some(l), |l: &mut L2| Some(l));
LockKp::new(prev, RcRefCellAccess::new(), next)
};
let lock3 = {
let prev: KpType<L2, Rc<RefCell<L3>>> =
Kp::new(|l: &L2| Some(&l.l3), |l: &mut L2| Some(&mut l.l3));
let next: KpType<L3, String> =
Kp::new(|l: &L3| Some(&l.value), |l: &mut L3| Some(&mut l.value));
LockKp::new(prev, RcRefCellAccess::new(), next)
};
let composed_1_2 = lock1.then_lock(lock2);
let composed_all = composed_1_2.then_lock(lock3);
let value = composed_all.get(&root);
assert!(value.is_some());
assert_eq!(value.unwrap(), "deep");
}
#[test]
fn test_rc_refcell_panic_on_clone_proof() {
use std::cell::RefCell;
use std::rc::Rc;
struct PanicOnClone {
data: String,
}
impl Clone for PanicOnClone {
fn clone(&self) -> Self {
panic!("❌ DEEP CLONE DETECTED! PanicOnClone was cloned in Rc<RefCell>!");
}
}
#[derive(Clone)]
struct Root {
level1: Rc<RefCell<Level1>>,
}
struct Level1 {
panic_data: PanicOnClone,
level2: Rc<RefCell<Level2>>,
}
impl Clone for Level1 {
fn clone(&self) -> Self {
panic!("❌ Level1 was deeply cloned in Rc<RefCell>!");
}
}
struct Level2 {
panic_data2: PanicOnClone,
value: i32,
}
impl Clone for Level2 {
fn clone(&self) -> Self {
panic!("❌ Level2 was deeply cloned in Rc<RefCell>!");
}
}
let root = Root {
level1: Rc::new(RefCell::new(Level1 {
panic_data: PanicOnClone {
data: "level1".to_string(),
},
level2: Rc::new(RefCell::new(Level2 {
panic_data2: PanicOnClone {
data: "level2".to_string(),
},
value: 123,
})),
})),
};
let lock1 = {
let prev: KpType<Root, Rc<RefCell<Level1>>> = Kp::new(
|r: &Root| Some(&r.level1),
|r: &mut Root| Some(&mut r.level1),
);
let next: KpType<Level1, Level1> =
Kp::new(|l: &Level1| Some(l), |l: &mut Level1| Some(l));
LockKp::new(prev, RcRefCellAccess::new(), next)
};
let lock2 = {
let prev: KpType<Level1, Rc<RefCell<Level2>>> = Kp::new(
|l: &Level1| Some(&l.level2),
|l: &mut Level1| Some(&mut l.level2),
);
let next: KpType<Level2, i32> = Kp::new(
|l: &Level2| Some(&l.value),
|l: &mut Level2| Some(&mut l.value),
);
LockKp::new(prev, RcRefCellAccess::new(), next)
};
let composed = lock1.then_lock(lock2);
let value = composed.get(&root);
assert!(value.is_some());
assert_eq!(*value.unwrap(), 123);
let value2 = composed.get(&root);
assert!(value2.is_some());
}
#[test]
fn test_rc_refcell_vs_arc_mutex() {
use std::cell::RefCell;
use std::rc::Rc;
#[derive(Clone)]
struct RcRoot {
data: Rc<RefCell<String>>,
}
#[derive(Clone)]
struct ArcRoot {
data: Arc<Mutex<String>>,
}
let rc_root = RcRoot {
data: Rc::new(RefCell::new("rc_value".to_string())),
};
let rc_kp = {
let prev: KpType<RcRoot, Rc<RefCell<String>>> = Kp::new(
|r: &RcRoot| Some(&r.data),
|r: &mut RcRoot| Some(&mut r.data),
);
let next: KpType<String, String> =
Kp::new(|s: &String| Some(s), |s: &mut String| Some(s));
LockKp::new(prev, RcRefCellAccess::new(), next)
};
let arc_root = ArcRoot {
data: Arc::new(Mutex::new("arc_value".to_string())),
};
let arc_kp = {
let prev: KpType<ArcRoot, Arc<Mutex<String>>> = Kp::new(
|r: &ArcRoot| Some(&r.data),
|r: &mut ArcRoot| Some(&mut r.data),
);
let next: KpType<String, String> =
Kp::new(|s: &String| Some(s), |s: &mut String| Some(s));
LockKp::new(prev, ArcMutexAccess::new(), next)
};
let rc_value = rc_kp.get(&rc_root);
let arc_value = arc_kp.get(&arc_root);
assert_eq!(rc_value.unwrap(), "rc_value");
assert_eq!(arc_value.unwrap(), "arc_value");
}
#[cfg(feature = "parking_lot")]
#[test]
fn test_parking_lot_mutex_basic() {
use parking_lot::Mutex;
#[derive(Clone)]
struct Root {
data: Arc<Mutex<String>>,
}
let root = Root {
data: Arc::new(Mutex::new("parking_lot_mutex".to_string())),
};
let lock_kp = {
let prev: KpType<Root, Arc<Mutex<String>>> =
Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let next: KpType<String, String> =
Kp::new(|s: &String| Some(s), |s: &mut String| Some(s));
LockKp::new(prev, ParkingLotMutexAccess::new(), next)
};
let value = lock_kp.get(&root);
assert_eq!(value.unwrap(), &"parking_lot_mutex".to_string());
}
#[cfg(feature = "parking_lot")]
#[test]
fn test_parking_lot_rwlock_basic() {
use parking_lot::RwLock;
#[derive(Clone)]
struct Root {
data: Arc<RwLock<Vec<i32>>>,
}
let root = Root {
data: Arc::new(RwLock::new(vec![1, 2, 3, 4, 5])),
};
let lock_kp = {
let prev: KpType<Root, Arc<RwLock<Vec<i32>>>> =
Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let next: KpType<Vec<i32>, Vec<i32>> =
Kp::new(|v: &Vec<i32>| Some(v), |v: &mut Vec<i32>| Some(v));
LockKp::new(prev, ParkingLotRwLockAccess::new(), next)
};
let value = lock_kp.get(&root);
assert_eq!(value.unwrap().len(), 5);
assert_eq!(value.unwrap()[2], 3);
}
#[cfg(feature = "parking_lot")]
#[test]
fn test_parking_lot_mutex_compose() {
use parking_lot::Mutex;
#[derive(Clone)]
struct Root {
level1: Arc<Mutex<Level1>>,
}
#[derive(Clone)]
struct Level1 {
level2: Arc<Mutex<i32>>,
}
let root = Root {
level1: Arc::new(Mutex::new(Level1 {
level2: Arc::new(Mutex::new(42)),
})),
};
let lock1 = {
let prev: KpType<Root, Arc<Mutex<Level1>>> = Kp::new(
|r: &Root| Some(&r.level1),
|r: &mut Root| Some(&mut r.level1),
);
let next: KpType<Level1, Level1> =
Kp::new(|l: &Level1| Some(l), |l: &mut Level1| Some(l));
LockKp::new(prev, ParkingLotMutexAccess::new(), next)
};
let lock2 = {
let prev: KpType<Level1, Arc<Mutex<i32>>> = Kp::new(
|l: &Level1| Some(&l.level2),
|l: &mut Level1| Some(&mut l.level2),
);
let next: KpType<i32, i32> = Kp::new(|n: &i32| Some(n), |n: &mut i32| Some(n));
LockKp::new(prev, ParkingLotMutexAccess::new(), next)
};
let composed = lock1.then_lock(lock2);
let value = composed.get(&root);
assert_eq!(value.unwrap(), &42);
}
#[cfg(feature = "parking_lot")]
#[test]
fn test_parking_lot_rwlock_write() {
use parking_lot::RwLock;
#[derive(Clone)]
struct Root {
data: Arc<RwLock<i32>>,
}
let mut root = Root {
data: Arc::new(RwLock::new(100)),
};
let lock_kp = {
let prev: KpType<Root, Arc<RwLock<i32>>> =
Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let next: KpType<i32, i32> = Kp::new(|n: &i32| Some(n), |n: &mut i32| Some(n));
LockKp::new(prev, ParkingLotRwLockAccess::new(), next)
};
let value = lock_kp.get(&root);
assert_eq!(value.unwrap(), &100);
let mut_value = lock_kp.get_mut(&mut root);
assert!(mut_value.is_some());
if let Some(v) = mut_value {
*v = 200;
}
let new_value = lock_kp.get(&root);
assert_eq!(new_value.unwrap(), &200);
}
#[cfg(feature = "parking_lot")]
#[test]
fn test_parking_lot_panic_on_clone_proof() {
use parking_lot::Mutex;
struct PanicOnClone {
data: String,
}
impl Clone for PanicOnClone {
fn clone(&self) -> Self {
panic!("❌ PARKING_LOT DEEP CLONE DETECTED! PanicOnClone was cloned!");
}
}
#[derive(Clone)]
struct Root {
level1: Arc<Mutex<Level1>>,
}
struct Level1 {
panic_data: PanicOnClone,
value: i32,
}
impl Clone for Level1 {
fn clone(&self) -> Self {
panic!("❌ Level1 was deeply cloned in parking_lot context!");
}
}
let root = Root {
level1: Arc::new(Mutex::new(Level1 {
panic_data: PanicOnClone {
data: "test".to_string(),
},
value: 123,
})),
};
let lock_kp = {
let prev: KpType<Root, Arc<Mutex<Level1>>> = Kp::new(
|r: &Root| Some(&r.level1),
|r: &mut Root| Some(&mut r.level1),
);
let next: KpType<Level1, i32> = Kp::new(
|l: &Level1| Some(&l.value),
|l: &mut Level1| Some(&mut l.value),
);
LockKp::new(prev, ParkingLotMutexAccess::new(), next)
};
let value = lock_kp.get(&root);
assert_eq!(value.unwrap(), &123);
}
#[test]
fn test_std_mutex_direct() {
use std::sync::Mutex;
struct Root {
data: Mutex<Inner>,
}
struct Inner {
value: i32,
}
let mut root = Root {
data: Mutex::new(Inner { value: 42 }),
};
let lock_kp = {
let prev: KpType<Root, Mutex<Inner>> =
Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let next: KpType<Inner, i32> = Kp::new(
|i: &Inner| Some(&i.value),
|i: &mut Inner| Some(&mut i.value),
);
LockKp::new(prev, StdMutexAccess::new(), next)
};
let value = lock_kp.get(&root);
assert_eq!(value, Some(&42));
lock_kp.get_mut(&mut root).map(|v| *v = 100);
let value = lock_kp.get(&root);
assert_eq!(value, Some(&100));
}
#[test]
fn test_std_rwlock_direct() {
use std::sync::RwLock;
struct Root {
data: RwLock<Inner>,
}
struct Inner {
value: String,
}
let mut root = Root {
data: RwLock::new(Inner {
value: "hello".to_string(),
}),
};
let lock_kp = {
let prev: KpType<Root, RwLock<Inner>> =
Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let next: KpType<Inner, String> = Kp::new(
|i: &Inner| Some(&i.value),
|i: &mut Inner| Some(&mut i.value),
);
LockKp::new(prev, StdRwLockAccess::new(), next)
};
let value = lock_kp.get(&root);
assert_eq!(value.as_ref().map(|s| s.as_str()), Some("hello"));
lock_kp.get_mut(&mut root).map(|v| *v = "world".to_string());
let value = lock_kp.get(&root);
assert_eq!(value.as_ref().map(|s| s.as_str()), Some("world"));
}
#[cfg(feature = "parking_lot")]
#[test]
fn test_parking_lot_mutex_direct() {
use parking_lot::Mutex;
struct Root {
data: Mutex<Inner>,
}
struct Inner {
value: i32,
}
let mut root = Root {
data: Mutex::new(Inner { value: 42 }),
};
let lock_kp = {
let prev: KpType<Root, Mutex<Inner>> =
Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let next: KpType<Inner, i32> = Kp::new(
|i: &Inner| Some(&i.value),
|i: &mut Inner| Some(&mut i.value),
);
LockKp::new(prev, DirectParkingLotMutexAccess::new(), next)
};
let value = lock_kp.get(&root);
assert_eq!(value, Some(&42));
lock_kp.get_mut(&mut root).map(|v| *v = 100);
let value = lock_kp.get(&root);
assert_eq!(value, Some(&100));
}
#[cfg(feature = "parking_lot")]
#[test]
fn test_parking_lot_rwlock_direct() {
use parking_lot::RwLock;
struct Root {
data: RwLock<Inner>,
}
struct Inner {
value: String,
}
let mut root = Root {
data: RwLock::new(Inner {
value: "hello".to_string(),
}),
};
let lock_kp = {
let prev: KpType<Root, RwLock<Inner>> =
Kp::new(|r: &Root| Some(&r.data), |r: &mut Root| Some(&mut r.data));
let next: KpType<Inner, String> = Kp::new(
|i: &Inner| Some(&i.value),
|i: &mut Inner| Some(&mut i.value),
);
LockKp::new(prev, DirectParkingLotRwLockAccess::new(), next)
};
let value = lock_kp.get(&root);
assert_eq!(value.as_ref().map(|s| s.as_str()), Some("hello"));
lock_kp.get_mut(&mut root).map(|v| *v = "world".to_string());
let value = lock_kp.get(&root);
assert_eq!(value.as_ref().map(|s| s.as_str()), Some("world"));
}
}