1use crate::util::log::write_error_log;
2use std::path::{Path, PathBuf};
3use std::sync::{Mutex, MutexGuard};
4
5pub fn safe_lock<'a, T>(mutex: &'a Mutex<T>, context: &str) -> MutexGuard<'a, T> {
8 mutex.lock().unwrap_or_else(|poisoned| {
9 write_error_log(
10 "safe_lock",
11 &format!("Mutex poisoned at [{}], recovering", context),
12 );
13 poisoned.into_inner()
14 })
15}
16
17pub struct LockFileGuard {
32 path: PathBuf,
33}
34
35impl LockFileGuard {
36 pub fn acquire(lock_path: &Path) -> Result<Self, String> {
42 const MAX_RETRIES: u32 = 20;
43 const RETRY_DELAY_MS: u64 = 50;
44
45 for attempt in 0..MAX_RETRIES {
46 match std::fs::File::create_new(lock_path) {
48 Ok(_) => {
49 return Ok(Self {
50 path: lock_path.to_path_buf(),
51 });
52 }
53 Err(_) if attempt < MAX_RETRIES - 1 => {
54 std::thread::sleep(std::time::Duration::from_millis(RETRY_DELAY_MS));
55 }
56 Err(e) => {
57 return Err(format!("文件被占用,请稍后重试: {}", e));
58 }
59 }
60 }
61 unreachable!()
62 }
63}
64
65impl Drop for LockFileGuard {
66 fn drop(&mut self) {
67 let _ = std::fs::remove_file(&self.path);
68 }
69}