diff options
Diffstat (limited to 'library/std/src/sys/windows/locks')
-rw-r--r-- | library/std/src/sys/windows/locks/condvar.rs | 52 | ||||
-rw-r--r-- | library/std/src/sys/windows/locks/mod.rs | 6 | ||||
-rw-r--r-- | library/std/src/sys/windows/locks/mutex.rs | 57 | ||||
-rw-r--r-- | library/std/src/sys/windows/locks/rwlock.rs | 42 |
4 files changed, 157 insertions, 0 deletions
diff --git a/library/std/src/sys/windows/locks/condvar.rs b/library/std/src/sys/windows/locks/condvar.rs new file mode 100644 index 000000000..be9a2abbe --- /dev/null +++ b/library/std/src/sys/windows/locks/condvar.rs @@ -0,0 +1,52 @@ +use crate::cell::UnsafeCell; +use crate::sys::c; +use crate::sys::locks::{mutex, Mutex}; +use crate::sys::os; +use crate::time::Duration; + +pub struct Condvar { + inner: UnsafeCell<c::CONDITION_VARIABLE>, +} + +pub type MovableCondvar = Condvar; + +unsafe impl Send for Condvar {} +unsafe impl Sync for Condvar {} + +impl Condvar { + #[inline] + pub const fn new() -> Condvar { + Condvar { inner: UnsafeCell::new(c::CONDITION_VARIABLE_INIT) } + } + + #[inline] + pub unsafe fn wait(&self, mutex: &Mutex) { + let r = c::SleepConditionVariableSRW(self.inner.get(), mutex::raw(mutex), c::INFINITE, 0); + debug_assert!(r != 0); + } + + pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { + let r = c::SleepConditionVariableSRW( + self.inner.get(), + mutex::raw(mutex), + crate::sys::windows::dur2timeout(dur), + 0, + ); + if r == 0 { + debug_assert_eq!(os::errno() as usize, c::ERROR_TIMEOUT as usize); + false + } else { + true + } + } + + #[inline] + pub unsafe fn notify_one(&self) { + c::WakeConditionVariable(self.inner.get()) + } + + #[inline] + pub unsafe fn notify_all(&self) { + c::WakeAllConditionVariable(self.inner.get()) + } +} diff --git a/library/std/src/sys/windows/locks/mod.rs b/library/std/src/sys/windows/locks/mod.rs new file mode 100644 index 000000000..d412ff152 --- /dev/null +++ b/library/std/src/sys/windows/locks/mod.rs @@ -0,0 +1,6 @@ +mod condvar; +mod mutex; +mod rwlock; +pub use condvar::{Condvar, MovableCondvar}; +pub use mutex::{MovableMutex, Mutex}; +pub use rwlock::{MovableRwLock, RwLock}; diff --git a/library/std/src/sys/windows/locks/mutex.rs b/library/std/src/sys/windows/locks/mutex.rs new file mode 100644 index 000000000..f91e8f9f5 --- /dev/null +++ b/library/std/src/sys/windows/locks/mutex.rs @@ -0,0 +1,57 @@ +//! System Mutexes +//! +//! The Windows implementation of mutexes is a little odd and it might 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::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 { + #[inline] + 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)); + } +} diff --git a/library/std/src/sys/windows/locks/rwlock.rs b/library/std/src/sys/windows/locks/rwlock.rs new file mode 100644 index 000000000..fa5ffe574 --- /dev/null +++ b/library/std/src/sys/windows/locks/rwlock.rs @@ -0,0 +1,42 @@ +use crate::cell::UnsafeCell; +use crate::sys::c; + +pub struct RwLock { + inner: UnsafeCell<c::SRWLOCK>, +} + +pub type MovableRwLock = RwLock; + +unsafe impl Send for RwLock {} +unsafe impl Sync for RwLock {} + +impl RwLock { + #[inline] + pub const fn new() -> RwLock { + RwLock { inner: UnsafeCell::new(c::SRWLOCK_INIT) } + } + #[inline] + pub unsafe fn read(&self) { + c::AcquireSRWLockShared(self.inner.get()) + } + #[inline] + pub unsafe fn try_read(&self) -> bool { + c::TryAcquireSRWLockShared(self.inner.get()) != 0 + } + #[inline] + pub unsafe fn write(&self) { + c::AcquireSRWLockExclusive(self.inner.get()) + } + #[inline] + pub unsafe fn try_write(&self) -> bool { + c::TryAcquireSRWLockExclusive(self.inner.get()) != 0 + } + #[inline] + pub unsafe fn read_unlock(&self) { + c::ReleaseSRWLockShared(self.inner.get()) + } + #[inline] + pub unsafe fn write_unlock(&self) { + c::ReleaseSRWLockExclusive(self.inner.get()) + } +} |