1#[cfg(windows)]
7use std::{io, ptr};
8
9#[cfg(windows)]
10use winapi::{
11 shared::winerror::ERROR_ALREADY_EXISTS,
12 um::{handleapi::CloseHandle, synchapi::CreateMutexA, winnt::HANDLE},
13};
14
15use super::errors::CodeError;
16
17pub struct AppMutex {
18 #[cfg(windows)]
19 handle: HANDLE,
20}
21
22#[cfg(windows)] unsafe impl Send for AppMutex {}
24
25impl AppMutex {
26 #[cfg(unix)]
27 pub fn new(_name: &str) -> Result<Self, CodeError> {
28 Ok(Self {})
29 }
30
31 #[cfg(windows)]
32 pub fn new(name: &str) -> Result<Self, CodeError> {
33 use std::ffi::CString;
34
35 let cname = CString::new(name).unwrap();
36 let handle = unsafe { CreateMutexA(ptr::null_mut(), 0, cname.as_ptr() as _) };
37
38 if !handle.is_null() {
39 return Ok(Self { handle });
40 }
41
42 let err = io::Error::last_os_error();
43 let raw = err.raw_os_error();
44 if raw == Some(ERROR_ALREADY_EXISTS as i32) {
47 return Err(CodeError::AppAlreadyLocked(name.to_string()));
48 }
49
50 Err(CodeError::AppLockFailed(err))
51 }
52}
53
54impl Drop for AppMutex {
55 fn drop(&mut self) {
56 #[cfg(windows)]
57 unsafe {
58 CloseHandle(self.handle)
59 };
60 }
61}