use core::cell::UnsafeCell; #[repr(C)] #[derive(Clone, Copy)] pub struct SrwLock { ptr: *mut core::ffi::c_void, } const SRWLOCK_INIT: SrwLock = SrwLock { ptr: core::ptr::null_mut(), }; type Boolean = u8; #[link(name = "kernel32")] extern "system" { pub fn AcquireSRWLockShared(srwlock: *mut SrwLock); pub fn AcquireSRWLockExclusive(srwlock: *mut SrwLock); pub fn TryAcquireSRWLockShared(srwlock: *mut SrwLock) -> Boolean; pub fn TryAcquireSRWLockExclusive(srwlock: *mut SrwLock) -> Boolean; pub fn ReleaseSRWLockShared(srwlock: *mut SrwLock); pub fn ReleaseSRWLockExclusive(srwlock: *mut SrwLock); } pub struct Mutex(UnsafeCell); unsafe impl Send for Mutex {} unsafe impl Sync for Mutex {} impl Mutex { #[inline] pub const fn new() -> Self { Self(UnsafeCell::new(SRWLOCK_INIT)) } /// Locks the mutex /// /// # Safety /// /// UB occurs if the mutex is already locked by the current thread and the /// `unsafe_lock` feature is enabled. #[inline] pub unsafe fn lock(&self) { unsafe { AcquireSRWLockExclusive(self.0.get()); } } /// If the mutex is unlocked, it is locked, and this function returns /// `true'. Otherwise, `false` is returned. #[inline] pub unsafe fn try_lock(&self) -> bool { unsafe { TryAcquireSRWLockExclusive(self.0.get()) != 0 } } /// Unlocks the mutex /// /// # Safety /// /// UB occurs if the mutex is already unlocked or if it has been locked on /// a different thread. #[inline] pub unsafe fn unlock(&self) { unsafe { ReleaseSRWLockExclusive(self.0.get()); } } pub unsafe fn is_locked(&self) -> bool { if self.try_lock() { unsafe { self.unlock(); } false } else { true } } } pub struct RwLock { inner: UnsafeCell, } 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 fn read(&self) { unsafe { c::AcquireSRWLockShared(self.inner.get()) } } #[inline] pub fn try_read(&self) -> bool { unsafe { c::TryAcquireSRWLockShared(self.inner.get()) != 0 } } #[inline] pub fn write(&self) { unsafe { c::AcquireSRWLockExclusive(self.inner.get()) } } #[inline] pub fn try_write(&self) -> bool { unsafe { 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()) } }