diff options
Diffstat (limited to 'src/windows.rs')
-rw-r--r-- | src/windows.rs | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/src/windows.rs b/src/windows.rs new file mode 100644 index 0000000..8f65877 --- /dev/null +++ b/src/windows.rs @@ -0,0 +1,73 @@ +use std::io; +use std::ptr; +use widestring::WideCString; +use winapi::shared::winerror::WAIT_TIMEOUT; +use winapi::um::handleapi::CloseHandle; +use winapi::um::synchapi::{CreateMutexW, ReleaseMutex, WaitForSingleObject}; +use winapi::um::winbase::{INFINITE, WAIT_ABANDONED, WAIT_OBJECT_0}; +use winapi::um::winnt::HANDLE; + +use crate::error::*; + +#[derive(Debug)] +pub(crate) struct RawNamedLock { + handle: HANDLE, +} + +unsafe impl Sync for RawNamedLock {} +unsafe impl Send for RawNamedLock {} + +impl RawNamedLock { + pub(crate) fn create(name: &str) -> Result<RawNamedLock> { + let name = WideCString::from_str(name).unwrap(); + let handle = unsafe { CreateMutexW(ptr::null_mut(), 0, name.as_ptr()) }; + + if handle.is_null() { + Err(Error::CreateFailed(io::Error::last_os_error())) + } else { + Ok(RawNamedLock { + handle, + }) + } + } + + pub(crate) fn try_lock(&self) -> Result<()> { + let rc = unsafe { WaitForSingleObject(self.handle, 0) }; + + if rc == WAIT_OBJECT_0 || rc == WAIT_ABANDONED { + Ok(()) + } else if rc == WAIT_TIMEOUT { + Err(Error::WouldBlock) + } else { + Err(Error::LockFailed) + } + } + + pub(crate) fn lock(&self) -> Result<()> { + let rc = unsafe { WaitForSingleObject(self.handle, INFINITE) }; + + if rc == WAIT_OBJECT_0 || rc == WAIT_ABANDONED { + Ok(()) + } else { + Err(Error::LockFailed) + } + } + + pub(crate) fn unlock(&self) -> Result<()> { + let rc = unsafe { ReleaseMutex(self.handle) }; + + if rc == 0 { + Err(Error::UnlockFailed) + } else { + Ok(()) + } + } +} + +impl Drop for RawNamedLock { + fn drop(&mut self) { + unsafe { + CloseHandle(self.handle); + } + } +} |