1 use std::io; 2 use std::ptr; 3 use widestring::WideCString; 4 use winapi::shared::winerror::WAIT_TIMEOUT; 5 use winapi::um::handleapi::CloseHandle; 6 use winapi::um::synchapi::{CreateMutexW, ReleaseMutex, WaitForSingleObject}; 7 use winapi::um::winbase::{INFINITE, WAIT_ABANDONED, WAIT_OBJECT_0}; 8 use winapi::um::winnt::HANDLE; 9 10 use crate::error::*; 11 12 #[derive(Debug)] 13 pub(crate) struct RawNamedLock { 14 handle: HANDLE, 15 } 16 17 unsafe impl Sync for RawNamedLock {} 18 unsafe impl Send for RawNamedLock {} 19 20 impl RawNamedLock { create(name: &str) -> Result<RawNamedLock>21 pub(crate) fn create(name: &str) -> Result<RawNamedLock> { 22 let name = WideCString::from_str(name).unwrap(); 23 let handle = unsafe { CreateMutexW(ptr::null_mut(), 0, name.as_ptr()) }; 24 25 if handle.is_null() { 26 Err(Error::CreateFailed(io::Error::last_os_error())) 27 } else { 28 Ok(RawNamedLock { 29 handle, 30 }) 31 } 32 } 33 try_lock(&self) -> Result<()>34 pub(crate) fn try_lock(&self) -> Result<()> { 35 let rc = unsafe { WaitForSingleObject(self.handle, 0) }; 36 37 if rc == WAIT_OBJECT_0 || rc == WAIT_ABANDONED { 38 Ok(()) 39 } else if rc == WAIT_TIMEOUT { 40 Err(Error::WouldBlock) 41 } else { 42 Err(Error::LockFailed) 43 } 44 } 45 lock(&self) -> Result<()>46 pub(crate) fn lock(&self) -> Result<()> { 47 let rc = unsafe { WaitForSingleObject(self.handle, INFINITE) }; 48 49 if rc == WAIT_OBJECT_0 || rc == WAIT_ABANDONED { 50 Ok(()) 51 } else { 52 Err(Error::LockFailed) 53 } 54 } 55 unlock(&self) -> Result<()>56 pub(crate) fn unlock(&self) -> Result<()> { 57 let rc = unsafe { ReleaseMutex(self.handle) }; 58 59 if rc == 0 { 60 Err(Error::UnlockFailed) 61 } else { 62 Ok(()) 63 } 64 } 65 } 66 67 impl Drop for RawNamedLock { drop(&mut self)68 fn drop(&mut self) { 69 unsafe { 70 CloseHandle(self.handle); 71 } 72 } 73 } 74