use core::ops::{Deref, DerefMut};
pub trait LockFor<L> {
type Data;
type Guard<'l>: DerefMut<Target = Self::Data>
where
Self: 'l;
fn lock(&self) -> Self::Guard<'_>;
}
pub trait RwLockFor<L> {
type Data;
type ReadGuard<'l>: Deref<Target = Self::Data>
where
Self: 'l;
type WriteGuard<'l>: DerefMut<Target = Self::Data>
where
Self: 'l;
fn read_lock(&self) -> Self::ReadGuard<'_>;
fn write_lock(&self) -> Self::WriteGuard<'_>;
}
pub trait UnlockedAccess<A> {
type Data;
type Guard<'l>: Deref<Target = Self::Data>
where
Self: 'l;
fn access(&self) -> Self::Guard<'_>;
}
pub trait OrderedLockAccess<T> {
type Lock;
fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock>;
}
pub trait DelegatedOrderedLockAccess<T> {
type Inner: OrderedLockAccess<T> + 'static;
fn delegate_ordered_lock_access(&self) -> &Self::Inner;
}
impl<T, O> OrderedLockAccess<T> for O
where
O: DelegatedOrderedLockAccess<T>,
{
type Lock = <O::Inner as OrderedLockAccess<T>>::Lock;
fn ordered_lock_access(&self) -> OrderedLockRef<'_, Self::Lock> {
self.delegate_ordered_lock_access().ordered_lock_access()
}
}
pub struct OrderedLockRef<'a, T>(&'a T);
impl<'a, T> OrderedLockRef<'a, T> {
pub fn new(lock: &'a T) -> Self {
Self(lock)
}
}
pub trait LockLevelFor<T> {
type Data;
}
pub trait ExclusiveLock<T>: 'static {
type Guard<'l>: DerefMut<Target = T>;
fn lock(&self) -> Self::Guard<'_>;
}
pub trait ReadWriteLock<T>: 'static {
type ReadGuard<'l>: Deref<Target = T>;
type WriteGuard<'l>: DerefMut<Target = T>;
fn read_lock(&self) -> Self::ReadGuard<'_>;
fn write_lock(&self) -> Self::WriteGuard<'_>;
}
impl<L, T> LockFor<L> for T
where
L: LockLevelFor<T>,
T: OrderedLockAccess<L::Data>,
T::Lock: ExclusiveLock<L::Data>,
{
type Data = L::Data;
type Guard<'l>
= <T::Lock as ExclusiveLock<L::Data>>::Guard<'l>
where
Self: 'l;
fn lock(&self) -> Self::Guard<'_> {
let OrderedLockRef(lock) = self.ordered_lock_access();
lock.lock()
}
}
impl<L, T> RwLockFor<L> for T
where
L: LockLevelFor<T>,
T: OrderedLockAccess<L::Data>,
T::Lock: ReadWriteLock<L::Data>,
{
type Data = L::Data;
type ReadGuard<'l>
= <T::Lock as ReadWriteLock<L::Data>>::ReadGuard<'l>
where
Self: 'l;
type WriteGuard<'l>
= <T::Lock as ReadWriteLock<L::Data>>::WriteGuard<'l>
where
Self: 'l;
fn read_lock(&self) -> Self::ReadGuard<'_> {
let OrderedLockRef(lock) = self.ordered_lock_access();
lock.read_lock()
}
fn write_lock(&self) -> Self::WriteGuard<'_> {
let OrderedLockRef(lock) = self.ordered_lock_access();
lock.write_lock()
}
}
pub trait UnlockedAccessMarkerFor<T> {
type Data: 'static;
fn unlocked_access(t: &T) -> &Self::Data;
}
impl<L, T> UnlockedAccess<L> for T
where
L: UnlockedAccessMarkerFor<T>,
{
type Data = <L as UnlockedAccessMarkerFor<T>>::Data;
type Guard<'l>
= &'l <L as UnlockedAccessMarkerFor<T>>::Data
where
Self: 'l;
fn access(&self) -> Self::Guard<'_> {
L::unlocked_access(self)
}
}
#[cfg(test)]
mod example {
use std::sync::{Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard};
use super::*;
enum LockLevel {}
impl<T> LockFor<LockLevel> for Mutex<T> {
type Data = T;
type Guard<'l>
= MutexGuard<'l, T>
where
Self: 'l;
fn lock(&self) -> Self::Guard<'_> {
self.lock().unwrap()
}
}
impl<T> RwLockFor<LockLevel> for RwLock<T> {
type Data = T;
type ReadGuard<'l>
= RwLockReadGuard<'l, T>
where
Self: 'l;
type WriteGuard<'l>
= RwLockWriteGuard<'l, T>
where
Self: 'l;
fn read_lock(&self) -> Self::ReadGuard<'_> {
self.read().unwrap()
}
fn write_lock(&self) -> Self::WriteGuard<'_> {
self.write().unwrap()
}
}
}