use std::marker::PhantomData;
pub trait Level {}
pub trait Lower<O: Level>: Level {}
#[derive(Debug)]
pub struct L0 {}
#[derive(Debug)]
pub struct L1 {}
#[derive(Debug)]
pub struct L2 {}
#[derive(Debug)]
pub struct L3 {}
#[derive(Debug)]
pub struct L4 {}
#[derive(Debug)]
pub struct L5 {}
impl Level for L0 {}
impl Level for L1 {}
impl Level for L2 {}
impl Level for L3 {}
impl Level for L4 {}
impl Level for L5 {}
impl Lower<L1> for L0 {}
impl Lower<L2> for L0 {}
impl Lower<L3> for L0 {}
impl Lower<L4> for L0 {}
impl Lower<L5> for L0 {}
impl Lower<L2> for L1 {}
impl Lower<L3> for L1 {}
impl Lower<L4> for L1 {}
impl Lower<L5> for L1 {}
impl Lower<L3> for L2 {}
impl Lower<L4> for L2 {}
impl Lower<L5> for L2 {}
impl Lower<L4> for L3 {}
impl Lower<L5> for L3 {}
impl Lower<L5> for L4 {}
pub trait Higher<O: Level>: Level {}
impl<L1: Level, L2: Level> Higher<L2> for L1 where L2: Lower<L1> {}
pub struct LockToken<'a, L: Level>(PhantomData<&'a mut L>);
impl<'a, L: Level> LockToken<'a, L> {
pub fn token(&mut self) -> LockToken<'_, L> {
LockToken(Default::default())
}
pub fn downgrade<LC: Higher<L>>(&mut self) -> LockToken<'_, LC> {
LockToken(Default::default())
}
pub fn downgraded<LP: Lower<L>>(_: LockToken<'a, LP>) -> Self {
LockToken(Default::default())
}
}
pub struct CleanLockToken;
impl CleanLockToken {
pub fn token(&mut self) -> LockToken<'_, L0> {
LockToken(Default::default())
}
pub fn downgrade<L: Level>(&mut self) -> LockToken<'_, L> {
LockToken(Default::default())
}
pub unsafe fn new() -> Self {
CleanLockToken
}
}
#[derive(Debug)]
pub struct Mutex<L: Level, T> {
inner: std::sync::Mutex<T>,
_phantom: PhantomData<L>,
}
impl<L: Level, T: Default> Default for Mutex<L, T> {
fn default() -> Self {
Self {
inner: Default::default(),
_phantom: Default::default(),
}
}
}
impl<L: Level, T> Mutex<L, T> {
pub fn new(val: T) -> Self {
Self {
inner: std::sync::Mutex::new(val),
_phantom: Default::default(),
}
}
pub fn lock<'a, LP: Lower<L> + 'a>(
&'a self,
lock_token: LockToken<'a, LP>,
) -> MutexGuard<'a, L, T> {
MutexGuard {
inner: self.inner.lock().unwrap(),
lock_token: LockToken::downgraded(lock_token),
}
}
pub fn try_lock<'a, LP: Lower<L> + 'a>(
&'a self,
lock_token: LockToken<'a, LP>,
) -> Option<MutexGuard<'a, L, T>> {
match self.inner.try_lock() {
Ok(inner) => Some(MutexGuard {
inner,
lock_token: LockToken::downgraded(lock_token),
}),
Err(std::sync::TryLockError::Poisoned(_)) => panic!("Poised lock"),
Err(std::sync::TryLockError::WouldBlock) => None,
}
}
pub fn try_lock_for<'a, LP: Lower<L> + 'a>(
&'a self,
lock_token: LockToken<'a, LP>,
duration: std::time::Duration,
) -> Option<MutexGuard<'a, L, T>> {
let try_counts = 16;
for _ in 0..try_counts {
if let Some(lock) = self.try_lock(LockToken::<LP>(Default::default())) {
return Some(lock);
}
std::thread::sleep(duration / try_counts)
}
self.try_lock(lock_token)
}
pub fn into_inner(self) -> T {
self.inner.into_inner().unwrap()
}
}
pub struct MutexGuard<'a, L: Level, T: ?Sized + 'a> {
inner: std::sync::MutexGuard<'a, T>,
lock_token: LockToken<'a, L>,
}
impl<'a, L: Level, T: ?Sized + 'a> MutexGuard<'a, L, T> {
pub fn token_split(&mut self) -> (&mut T, LockToken<'_, L>) {
(&mut self.inner, self.lock_token.token())
}
}
impl<'a, L: Level, T: ?Sized + 'a> std::ops::Deref for MutexGuard<'a, L, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.inner.deref()
}
}
impl<'a, L: Level, T: ?Sized + 'a> std::ops::DerefMut for MutexGuard<'a, L, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.inner.deref_mut()
}
}
pub struct RwLock<L: Level, T> {
inner: std::sync::RwLock<T>,
_phantom: PhantomData<L>,
}
impl<L: Level, T: Default> Default for RwLock<L, T> {
fn default() -> Self {
Self {
inner: Default::default(),
_phantom: Default::default(),
}
}
}
impl<L: Level, T> RwLock<L, T> {
pub fn new(val: T) -> Self {
Self {
inner: std::sync::RwLock::new(val),
_phantom: Default::default(),
}
}
pub fn into_inner(self) -> T {
self.inner.into_inner().unwrap()
}
pub fn write<'a, LP: Lower<L> + 'a>(
&'a self,
lock_token: LockToken<'a, LP>,
) -> RwLockWriteGuard<'a, L, T> {
RwLockWriteGuard {
inner: self.inner.write().unwrap(),
lock_token: LockToken::downgraded(lock_token),
}
}
pub fn read<'a, LP: Lower<L> + 'a>(
&'a self,
lock_token: LockToken<'a, LP>,
) -> RwLockReadGuard<'a, L, T> {
RwLockReadGuard {
inner: self.inner.read().unwrap(),
lock_token: LockToken::downgraded(lock_token),
}
}
}
pub struct RwLockWriteGuard<'a, L: Level, T> {
inner: std::sync::RwLockWriteGuard<'a, T>,
lock_token: LockToken<'a, L>,
}
impl<'a, L: Level, T> RwLockWriteGuard<'a, L, T> {
pub fn token_split(&mut self) -> (&mut T, LockToken<'_, L>) {
(&mut self.inner, self.lock_token.token())
}
}
impl<'a, L: Level, T> std::ops::Deref for RwLockWriteGuard<'a, L, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.inner.deref()
}
}
impl<'a, L: Level, T> std::ops::DerefMut for RwLockWriteGuard<'a, L, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.inner.deref_mut()
}
}
pub struct RwLockReadGuard<'a, L: Level, T> {
inner: std::sync::RwLockReadGuard<'a, T>,
lock_token: LockToken<'a, L>,
}
impl<'a, L: Level, T> RwLockReadGuard<'a, L, T> {
pub fn token_split(&mut self) -> (&T, LockToken<'_, L>) {
(&self.inner, self.lock_token.token())
}
}
impl<'a, L: Level, T> std::ops::Deref for RwLockReadGuard<'a, L, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.inner.deref()
}
}
#[cfg(feature = "tokio")]
#[derive(Debug)]
pub struct AsyncMutex<L: Level, T> {
inner: tokio::sync::Mutex<T>,
_phantom: PhantomData<L>,
}
#[cfg(feature = "tokio")]
impl<L: Level, T> AsyncMutex<L, T> {
pub fn new(val: T) -> Self {
Self {
inner: tokio::sync::Mutex::new(val),
_phantom: Default::default(),
}
}
pub async fn lock<'a, LP: Lower<L> + 'a>(
&'a self,
lock_token: LockToken<'a, LP>,
) -> AsyncMutexGuard<'a, L, T> {
AsyncMutexGuard {
inner: self.inner.lock().await,
lock_token: LockToken::downgraded(lock_token),
}
}
pub fn try_lock<'a, LP: Lower<L> + 'a>(
&'a self,
lock_token: LockToken<'a, LP>,
) -> Result<AsyncMutexGuard<'a, L, T>, tokio::sync::TryLockError> {
self.inner.try_lock().map(|inner| AsyncMutexGuard {
inner,
lock_token: LockToken::downgraded(lock_token),
})
}
pub fn into_inner(self) -> T {
self.inner.into_inner()
}
}
#[cfg(feature = "tokio")]
impl<L: Level, T: Default> Default for AsyncMutex<L, T> {
fn default() -> Self {
Self {
inner: Default::default(),
_phantom: Default::default(),
}
}
}
#[cfg(feature = "tokio")]
pub struct AsyncMutexGuard<'a, L: Level, T: ?Sized + 'a> {
inner: tokio::sync::MutexGuard<'a, T>,
lock_token: LockToken<'a, L>,
}
#[cfg(feature = "tokio")]
impl<'a, L: Level, T: ?Sized + 'a> AsyncMutexGuard<'a, L, T> {
pub fn token_split(&mut self) -> (&mut T, LockToken<'_, L>) {
(&mut self.inner, self.lock_token.token())
}
}
#[cfg(feature = "tokio")]
impl<'a, L: Level, T: ?Sized + 'a> std::ops::Deref for AsyncMutexGuard<'a, L, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.inner.deref()
}
}
#[cfg(feature = "tokio")]
impl<'a, L: Level, T: ?Sized + 'a> std::ops::DerefMut for AsyncMutexGuard<'a, L, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.inner.deref_mut()
}
}
#[inline]
pub fn check_no_locks(_: LockToken<'_, L0>) {}