]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys/windows/mutex.rs
Auto merge of #86663 - fee1-dead:use-rustdoc-css, r=GuillaumeGomez
[rust.git] / library / std / src / sys / windows / mutex.rs
1 //! System Mutexes
2 //!
3 //! The Windows implementation of mutexes is a little odd and it may not be
4 //! immediately obvious what's going on. The primary oddness is that SRWLock is
5 //! used instead of CriticalSection, and this is done because:
6 //!
7 //! 1. SRWLock is several times faster than CriticalSection according to
8 //!    benchmarks performed on both Windows 8 and Windows 7.
9 //!
10 //! 2. CriticalSection allows recursive locking while SRWLock deadlocks. The
11 //!    Unix implementation deadlocks so consistency is preferred. See #19962 for
12 //!    more details.
13 //!
14 //! 3. While CriticalSection is fair and SRWLock is not, the current Rust policy
15 //!    is that there are no guarantees of fairness.
16
17 use crate::cell::UnsafeCell;
18 use crate::mem::MaybeUninit;
19 use crate::sys::c;
20
21 pub struct Mutex {
22     srwlock: UnsafeCell<c::SRWLOCK>,
23 }
24
25 // Windows SRW Locks are movable (while not borrowed).
26 pub type MovableMutex = Mutex;
27
28 unsafe impl Send for Mutex {}
29 unsafe impl Sync for Mutex {}
30
31 #[inline]
32 pub unsafe fn raw(m: &Mutex) -> c::PSRWLOCK {
33     m.srwlock.get()
34 }
35
36 impl Mutex {
37     pub const fn new() -> Mutex {
38         Mutex { srwlock: UnsafeCell::new(c::SRWLOCK_INIT) }
39     }
40     #[inline]
41     pub unsafe fn init(&mut self) {}
42
43     #[inline]
44     pub unsafe fn lock(&self) {
45         c::AcquireSRWLockExclusive(raw(self));
46     }
47
48     #[inline]
49     pub unsafe fn try_lock(&self) -> bool {
50         c::TryAcquireSRWLockExclusive(raw(self)) != 0
51     }
52
53     #[inline]
54     pub unsafe fn unlock(&self) {
55         c::ReleaseSRWLockExclusive(raw(self));
56     }
57
58     #[inline]
59     pub unsafe fn destroy(&self) {
60         // SRWLock does not need to be destroyed.
61     }
62 }
63
64 pub struct ReentrantMutex {
65     inner: MaybeUninit<UnsafeCell<c::CRITICAL_SECTION>>,
66 }
67
68 unsafe impl Send for ReentrantMutex {}
69 unsafe impl Sync for ReentrantMutex {}
70
71 impl ReentrantMutex {
72     pub const fn uninitialized() -> ReentrantMutex {
73         ReentrantMutex { inner: MaybeUninit::uninit() }
74     }
75
76     pub unsafe fn init(&self) {
77         c::InitializeCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
78     }
79
80     pub unsafe fn lock(&self) {
81         c::EnterCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
82     }
83
84     #[inline]
85     pub unsafe fn try_lock(&self) -> bool {
86         c::TryEnterCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr())) != 0
87     }
88
89     pub unsafe fn unlock(&self) {
90         c::LeaveCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
91     }
92
93     pub unsafe fn destroy(&self) {
94         c::DeleteCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
95     }
96 }