]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys_common/mutex.rs
Rollup merge of #67686 - ssomers:keys_start_slasher, r=Mark-Simulacrum
[rust.git] / src / libstd / sys_common / mutex.rs
1 use crate::sys::mutex as imp;
2
3 /// An OS-based mutual exclusion lock.
4 ///
5 /// This is the thinnest cross-platform wrapper around OS mutexes. All usage of
6 /// this mutex is unsafe and it is recommended to instead use the safe wrapper
7 /// at the top level of the crate instead of this type.
8 pub struct Mutex(imp::Mutex);
9
10 unsafe impl Sync for Mutex {}
11
12 impl Mutex {
13     /// Creates a new mutex for use.
14     ///
15     /// Behavior is undefined if the mutex is moved after it is
16     /// first used with any of the functions below.
17     /// Also, until `init` is called, behavior is undefined if this
18     /// mutex is ever used reentrantly, i.e., `raw_lock` or `try_lock`
19     /// are called by the thread currently holding the lock.
20     pub const fn new() -> Mutex {
21         Mutex(imp::Mutex::new())
22     }
23
24     /// Prepare the mutex for use.
25     ///
26     /// This should be called once the mutex is at a stable memory address.
27     /// If called, this must be the very first thing that happens to the mutex.
28     /// Calling it in parallel with or after any operation (including another
29     /// `init()`) is undefined behavior.
30     #[inline]
31     pub unsafe fn init(&mut self) {
32         self.0.init()
33     }
34
35     /// Locks the mutex blocking the current thread until it is available.
36     ///
37     /// Behavior is undefined if the mutex has been moved between this and any
38     /// previous function call.
39     #[inline]
40     pub unsafe fn raw_lock(&self) {
41         self.0.lock()
42     }
43
44     /// Calls raw_lock() and then returns an RAII guard to guarantee the mutex
45     /// will be unlocked.
46     #[inline]
47     pub unsafe fn lock(&self) -> MutexGuard<'_> {
48         self.raw_lock();
49         MutexGuard(&self.0)
50     }
51
52     /// Attempts to lock the mutex without blocking, returning whether it was
53     /// successfully acquired or not.
54     ///
55     /// Behavior is undefined if the mutex has been moved between this and any
56     /// previous function call.
57     #[inline]
58     pub unsafe fn try_lock(&self) -> bool {
59         self.0.try_lock()
60     }
61
62     /// Unlocks the mutex.
63     ///
64     /// Behavior is undefined if the current thread does not actually hold the
65     /// mutex.
66     ///
67     /// Consider switching from the pair of raw_lock() and raw_unlock() to
68     /// lock() whenever possible.
69     #[inline]
70     pub unsafe fn raw_unlock(&self) {
71         self.0.unlock()
72     }
73
74     /// Deallocates all resources associated with this mutex.
75     ///
76     /// Behavior is undefined if there are current or will be future users of
77     /// this mutex.
78     #[inline]
79     pub unsafe fn destroy(&self) {
80         self.0.destroy()
81     }
82 }
83
84 // not meant to be exported to the outside world, just the containing module
85 pub fn raw(mutex: &Mutex) -> &imp::Mutex {
86     &mutex.0
87 }
88
89 #[must_use]
90 /// A simple RAII utility for the above Mutex without the poisoning semantics.
91 pub struct MutexGuard<'a>(&'a imp::Mutex);
92
93 impl Drop for MutexGuard<'_> {
94     #[inline]
95     fn drop(&mut self) {
96         unsafe {
97             self.0.unlock();
98         }
99     }
100 }