96 lines
2.5 KiB
Rust
96 lines
2.5 KiB
Rust
//! System Mutexes
|
|
//!
|
|
//! The Windows implementation of mutexes is a little odd and it may not be
|
|
//! immediately obvious what's going on. The primary oddness is that SRWLock is
|
|
//! used instead of CriticalSection, and this is done because:
|
|
//!
|
|
//! 1. SRWLock is several times faster than CriticalSection according to
|
|
//! benchmarks performed on both Windows 8 and Windows 7.
|
|
//!
|
|
//! 2. CriticalSection allows recursive locking while SRWLock deadlocks. The
|
|
//! Unix implementation deadlocks so consistency is preferred. See #19962 for
|
|
//! more details.
|
|
//!
|
|
//! 3. While CriticalSection is fair and SRWLock is not, the current Rust policy
|
|
//! is that there are no guarantees of fairness.
|
|
|
|
use crate::cell::UnsafeCell;
|
|
use crate::mem::MaybeUninit;
|
|
use crate::sys::c;
|
|
|
|
pub struct Mutex {
|
|
srwlock: UnsafeCell<c::SRWLOCK>,
|
|
}
|
|
|
|
// Windows SRW Locks are movable (while not borrowed).
|
|
pub type MovableMutex = Mutex;
|
|
|
|
unsafe impl Send for Mutex {}
|
|
unsafe impl Sync for Mutex {}
|
|
|
|
#[inline]
|
|
pub unsafe fn raw(m: &Mutex) -> c::PSRWLOCK {
|
|
m.srwlock.get()
|
|
}
|
|
|
|
impl Mutex {
|
|
pub const fn new() -> Mutex {
|
|
Mutex { srwlock: UnsafeCell::new(c::SRWLOCK_INIT) }
|
|
}
|
|
#[inline]
|
|
pub unsafe fn init(&mut self) {}
|
|
|
|
#[inline]
|
|
pub unsafe fn lock(&self) {
|
|
c::AcquireSRWLockExclusive(raw(self));
|
|
}
|
|
|
|
#[inline]
|
|
pub unsafe fn try_lock(&self) -> bool {
|
|
c::TryAcquireSRWLockExclusive(raw(self)) != 0
|
|
}
|
|
|
|
#[inline]
|
|
pub unsafe fn unlock(&self) {
|
|
c::ReleaseSRWLockExclusive(raw(self));
|
|
}
|
|
|
|
#[inline]
|
|
pub unsafe fn destroy(&self) {
|
|
// SRWLock does not need to be destroyed.
|
|
}
|
|
}
|
|
|
|
pub struct ReentrantMutex {
|
|
inner: MaybeUninit<UnsafeCell<c::CRITICAL_SECTION>>,
|
|
}
|
|
|
|
unsafe impl Send for ReentrantMutex {}
|
|
unsafe impl Sync for ReentrantMutex {}
|
|
|
|
impl ReentrantMutex {
|
|
pub const fn uninitialized() -> ReentrantMutex {
|
|
ReentrantMutex { inner: MaybeUninit::uninit() }
|
|
}
|
|
|
|
pub unsafe fn init(&self) {
|
|
c::InitializeCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
|
|
}
|
|
|
|
pub unsafe fn lock(&self) {
|
|
c::EnterCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
|
|
}
|
|
|
|
#[inline]
|
|
pub unsafe fn try_lock(&self) -> bool {
|
|
c::TryEnterCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr())) != 0
|
|
}
|
|
|
|
pub unsafe fn unlock(&self) {
|
|
c::LeaveCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
|
|
}
|
|
|
|
pub unsafe fn destroy(&self) {
|
|
c::DeleteCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
|
|
}
|
|
}
|