nitric_lock/
mutex.rs

1use std::{cell::UnsafeCell, marker::PhantomData, ops::Deref, ops::DerefMut};
2
3use lock_api::RawMutex as Unused0;
4use parking_lot::RawMutex;
5
6use crate::{LockInfo, RawLockGuard, ReadLock, WriteLock};
7
8pub fn new_mutex<T>(data: T, id: usize) -> Mutex<T> {
9    Mutex {
10        data: UnsafeCell::new(data),
11        id,
12        raw: RawMutex::INIT,
13    }
14}
15
16pub struct Mutex<T> {
17    data: UnsafeCell<T>,
18    id: usize,
19    raw: RawMutex,
20}
21
22impl<T> Mutex<T> {
23    pub fn lock_id(&self) -> usize {
24        self.id
25    }
26
27    // TODO: decide whether to expose them, and how
28    // TODO: (simply exposing would easily allow deadlocks)
29    /*
30    pub unsafe fn lock(&self) -> MutexGuard<'_, T> {
31        self.raw.lock();
32
33        unsafe { self.acquire_guard() }
34    }
35
36    pub unsafe fn try_lock(&self) -> Option<MutexGuard<'_, T>> {
37        match self.raw.try_lock() {
38            true => unsafe { Some(self.acquire_guard()) },
39            false => None,
40        }
41    }
42    */
43
44    pub unsafe fn raw(&self) -> &RawMutex {
45        &self.raw
46    }
47
48    pub unsafe fn acquire_guard(&self) -> MutexGuard<'_, T> {
49        MutexGuard {
50            marker: PhantomData,
51            mutex: self,
52        }
53    }
54}
55
56impl<'a, T> ReadLock<'a> for &'a Mutex<T>
57where
58    T: 'a,
59{
60    type Output = MutexGuard<'a, T>;
61
62    unsafe fn lock_info(&self) -> LockInfo<'_> {
63        LockInfo {
64            id: self.lock_id(),
65            guard: RawLockGuard::RawMutex(self.raw()),
66        }
67    }
68
69    unsafe fn lock_unchecked(self) -> <Self as ReadLock<'a>>::Output {
70        self.acquire_guard()
71    }
72}
73
74impl<'a, T> WriteLock<'a> for &'a Mutex<T>
75where
76    T: 'a,
77{
78    type Output = MutexGuard<'a, T>;
79
80    unsafe fn lock_info(&self) -> LockInfo<'_> {
81        LockInfo {
82            id: self.lock_id(),
83            guard: RawLockGuard::RawMutex(self.raw()),
84        }
85    }
86
87    unsafe fn lock_unchecked(self) -> <Self as WriteLock<'a>>::Output {
88        self.acquire_guard()
89    }
90}
91
92pub struct MutexGuard<'a, T> {
93    marker: PhantomData<(&'a mut T, *mut ())>,
94    mutex: &'a Mutex<T>,
95}
96
97impl<T> Deref for MutexGuard<'_, T> {
98    type Target = T;
99
100    fn deref(&self) -> &<Self as Deref>::Target {
101        unsafe { &*self.mutex.data.get() }
102    }
103}
104
105impl<T> DerefMut for MutexGuard<'_, T> {
106    fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
107        unsafe { &mut *self.mutex.data.get() }
108    }
109}
110
111impl<T> Drop for MutexGuard<'_, T> {
112    fn drop(&mut self) {
113        self.mutex.raw.unlock();
114    }
115}