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:
7 //! 1. SRWLock is several times faster than CriticalSection according to
8 //! benchmarks performed on both Windows 8 and Windows 7.
10 //! 2. CriticalSection allows recursive locking while SRWLock deadlocks. The
11 //! Unix implementation deadlocks so consistency is preferred. See #19962 for
14 //! 3. While CriticalSection is fair and SRWLock is not, the current Rust policy
15 //! is that there are no guarantees of fairness.
17 use crate::cell::UnsafeCell;
18 use crate::mem::MaybeUninit;
22 srwlock: UnsafeCell<c::SRWLOCK>,
25 // Windows SRW Locks are movable (while not borrowed).
26 pub type MovableMutex = Mutex;
28 unsafe impl Send for Mutex {}
29 unsafe impl Sync for Mutex {}
32 pub unsafe fn raw(m: &Mutex) -> c::PSRWLOCK {
37 pub const fn new() -> Mutex {
38 Mutex { srwlock: UnsafeCell::new(c::SRWLOCK_INIT) }
41 pub unsafe fn init(&mut self) {}
44 pub unsafe fn lock(&self) {
45 c::AcquireSRWLockExclusive(raw(self));
49 pub unsafe fn try_lock(&self) -> bool {
50 c::TryAcquireSRWLockExclusive(raw(self)) != 0
54 pub unsafe fn unlock(&self) {
55 c::ReleaseSRWLockExclusive(raw(self));
59 pub unsafe fn destroy(&self) {
60 // SRWLock does not need to be destroyed.
64 pub struct ReentrantMutex {
65 inner: MaybeUninit<UnsafeCell<c::CRITICAL_SECTION>>,
68 unsafe impl Send for ReentrantMutex {}
69 unsafe impl Sync for ReentrantMutex {}
72 pub const fn uninitialized() -> ReentrantMutex {
73 ReentrantMutex { inner: MaybeUninit::uninit() }
76 pub unsafe fn init(&self) {
77 c::InitializeCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
80 pub unsafe fn lock(&self) {
81 c::EnterCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
85 pub unsafe fn try_lock(&self) -> bool {
86 c::TryEnterCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr())) != 0
89 pub unsafe fn unlock(&self) {
90 c::LeaveCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
93 pub unsafe fn destroy(&self) {
94 c::DeleteCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));