]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys_common/mutex.rs
Auto merge of #96495 - Dylan-DPC:rollup-9lm4tpp, r=Dylan-DPC
[rust.git] / library / std / src / sys_common / mutex.rs
1 use crate::sys::locks as imp;
2
3 /// An OS-based mutual exclusion lock, meant for use in static variables.
4 ///
5 /// This mutex has a const constructor ([`StaticMutex::new`]), does not
6 /// implement `Drop` to cleanup resources, and causes UB when used reentrantly.
7 ///
8 /// This mutex does not implement poisoning.
9 ///
10 /// This is a wrapper around `imp::Mutex` that does *not* call `init()` and
11 /// `destroy()`.
12 pub struct StaticMutex(imp::Mutex);
13
14 unsafe impl Sync for StaticMutex {}
15
16 impl StaticMutex {
17     /// Creates a new mutex for use.
18     pub const fn new() -> Self {
19         Self(imp::Mutex::new())
20     }
21
22     /// Calls raw_lock() and then returns an RAII guard to guarantee the mutex
23     /// will be unlocked.
24     ///
25     /// It is undefined behaviour to call this function while locked by the
26     /// same thread.
27     #[inline]
28     pub unsafe fn lock(&'static self) -> StaticMutexGuard {
29         self.0.lock();
30         StaticMutexGuard(&self.0)
31     }
32 }
33
34 #[must_use]
35 pub struct StaticMutexGuard(&'static imp::Mutex);
36
37 impl Drop for StaticMutexGuard {
38     #[inline]
39     fn drop(&mut self) {
40         unsafe {
41             self.0.unlock();
42         }
43     }
44 }
45
46 /// An OS-based mutual exclusion lock.
47 ///
48 /// This mutex does *not* have a const constructor, cleans up its resources in
49 /// its `Drop` implementation, may safely be moved (when not borrowed), and
50 /// does not cause UB when used reentrantly.
51 ///
52 /// This mutex does not implement poisoning.
53 ///
54 /// This is either a wrapper around `Box<imp::Mutex>` or `imp::Mutex`,
55 /// depending on the platform. It is boxed on platforms where `imp::Mutex` may
56 /// not be moved.
57 pub struct MovableMutex(imp::MovableMutex);
58
59 unsafe impl Sync for MovableMutex {}
60
61 impl MovableMutex {
62     /// Creates a new mutex.
63     pub fn new() -> Self {
64         let mut mutex = imp::MovableMutex::from(imp::Mutex::new());
65         unsafe { mutex.init() };
66         Self(mutex)
67     }
68
69     pub(super) fn raw(&self) -> &imp::Mutex {
70         &self.0
71     }
72
73     /// Locks the mutex blocking the current thread until it is available.
74     #[inline]
75     pub fn raw_lock(&self) {
76         unsafe { self.0.lock() }
77     }
78
79     /// Attempts to lock the mutex without blocking, returning whether it was
80     /// successfully acquired or not.
81     #[inline]
82     pub fn try_lock(&self) -> bool {
83         unsafe { self.0.try_lock() }
84     }
85
86     /// Unlocks the mutex.
87     ///
88     /// Behavior is undefined if the current thread does not actually hold the
89     /// mutex.
90     #[inline]
91     pub unsafe fn raw_unlock(&self) {
92         self.0.unlock()
93     }
94 }
95
96 impl Drop for MovableMutex {
97     fn drop(&mut self) {
98         unsafe { self.0.destroy() };
99     }
100 }