loom/sync/
mutex.rs

1use crate::rt;
2
3use std::ops;
4use std::sync::{LockResult, TryLockError, TryLockResult};
5
6/// Mock implementation of `std::sync::Mutex`.
7#[derive(Debug)]
8pub struct Mutex<T: ?Sized> {
9    object: rt::Mutex,
10    data: std::sync::Mutex<T>,
11}
12
13/// Mock implementation of `std::sync::MutexGuard`.
14#[derive(Debug)]
15pub struct MutexGuard<'a, T: ?Sized> {
16    lock: &'a Mutex<T>,
17    data: Option<std::sync::MutexGuard<'a, T>>,
18}
19
20impl<T> Mutex<T> {
21    /// Creates a new mutex in an unlocked state ready for use.
22    pub fn new(data: T) -> Mutex<T> {
23        Mutex {
24            data: std::sync::Mutex::new(data),
25            object: rt::Mutex::new(true),
26        }
27    }
28
29    /// Consumes this mutex, returning the underlying data.
30    pub fn into_inner(self) -> LockResult<T> {
31        Ok(self.data.into_inner().unwrap())
32    }
33}
34
35impl<T: ?Sized> Mutex<T> {
36    /// Acquires a mutex, blocking the current thread until it is able to do so.
37    #[track_caller]
38    pub fn lock(&self) -> LockResult<MutexGuard<'_, T>> {
39        self.object.acquire_lock(location!());
40
41        Ok(MutexGuard {
42            lock: self,
43            data: Some(self.data.lock().unwrap()),
44        })
45    }
46
47    /// Attempts to acquire this lock.
48    ///
49    /// If the lock could not be acquired at this time, then `Err` is returned.
50    /// Otherwise, an RAII guard is returned. The lock will be unlocked when the
51    /// guard is dropped.
52    ///
53    /// This function does not block.
54    #[track_caller]
55    pub fn try_lock(&self) -> TryLockResult<MutexGuard<'_, T>> {
56        if self.object.try_acquire_lock(location!()) {
57            Ok(MutexGuard {
58                lock: self,
59                data: Some(self.data.lock().unwrap()),
60            })
61        } else {
62            Err(TryLockError::WouldBlock)
63        }
64    }
65
66    /// Returns a mutable reference to the underlying data.
67    pub fn get_mut(&mut self) -> LockResult<&mut T> {
68        Ok(self.data.get_mut().unwrap())
69    }
70}
71
72impl<T: ?Sized + Default> Default for Mutex<T> {
73    /// Creates a `Mutex<T>`, with the `Default` value for T.
74    fn default() -> Self {
75        Self::new(Default::default())
76    }
77}
78
79impl<T> From<T> for Mutex<T> {
80    /// Creates a new mutex in an unlocked state ready for use.
81    /// This is equivalent to [`Mutex::new`].
82    fn from(t: T) -> Self {
83        Self::new(t)
84    }
85}
86
87impl<'a, T: ?Sized + 'a> MutexGuard<'a, T> {
88    pub(super) fn unborrow(&mut self) {
89        self.data = None;
90    }
91
92    pub(super) fn reborrow(&mut self) {
93        self.data = Some(self.lock.data.lock().unwrap());
94    }
95
96    pub(super) fn rt(&self) -> &rt::Mutex {
97        &self.lock.object
98    }
99}
100
101impl<'a, T: ?Sized> ops::Deref for MutexGuard<'a, T> {
102    type Target = T;
103
104    fn deref(&self) -> &T {
105        self.data.as_ref().unwrap().deref()
106    }
107}
108
109impl<'a, T: ?Sized> ops::DerefMut for MutexGuard<'a, T> {
110    fn deref_mut(&mut self) -> &mut T {
111        self.data.as_mut().unwrap().deref_mut()
112    }
113}
114
115impl<'a, T: ?Sized + 'a> Drop for MutexGuard<'a, T> {
116    fn drop(&mut self) {
117        self.data = None;
118        self.lock.object.release_lock();
119    }
120}