use crate::util::log::write_error_log;
use std::path::{Path, PathBuf};
use std::sync::{Mutex, MutexGuard};
pub fn safe_lock<'a, T>(mutex: &'a Mutex<T>, context: &str) -> MutexGuard<'a, T> {
mutex.lock().unwrap_or_else(|poisoned| {
write_error_log(
"safe_lock",
&format!("Mutex poisoned at [{}], recovering", context),
);
poisoned.into_inner()
})
}
pub struct LockFileGuard {
path: PathBuf,
}
impl LockFileGuard {
pub fn acquire(lock_path: &Path) -> Result<Self, String> {
const MAX_RETRIES: u32 = 20;
const RETRY_DELAY_MS: u64 = 50;
for attempt in 0..MAX_RETRIES {
match std::fs::File::create_new(lock_path) {
Ok(_) => {
return Ok(Self {
path: lock_path.to_path_buf(),
});
}
Err(_) if attempt < MAX_RETRIES - 1 => {
std::thread::sleep(std::time::Duration::from_millis(RETRY_DELAY_MS));
}
Err(e) => {
return Err(format!("文件被占用,请稍后重试: {}", e));
}
}
}
unreachable!()
}
}
impl Drop for LockFileGuard {
fn drop(&mut self) {
let _ = std::fs::remove_file(&self.path);
}
}