aboutsummaryrefslogtreecommitdiff
path: root/src/windows.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/windows.rs')
-rw-r--r--src/windows.rs73
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);
+ }
+ }
+}