1use std::{
3 collections::HashMap,
4 path::{Path, PathBuf},
5 sync::{Arc, Mutex, RwLock},
6};
7
8use crate::{AbsolutePath, Result};
9
10#[derive(Debug, Default)]
13pub struct PathSync {
14 locks: Arc<RwLock<HashMap<PathBuf, Arc<Mutex<()>>>>>,
15}
16
17impl PathSync {
18 pub fn new() -> Self {
20 Self {
21 locks: Arc::new(RwLock::new(HashMap::new())),
22 }
23 }
24
25 pub fn with_sync_path(
27 &self,
28 path: &Path,
29 mut f: impl FnMut(&Path) -> Result<()>,
30 ) -> Result<()> {
31 let entry = {
33 let locks = self.locks.clone();
34 let mut locks = locks.write()?;
35 locks
36 .entry(path.to_path_buf())
37 .or_insert_with(|| Arc::new(Mutex::new(())))
38 .clone()
39 };
40 let _guard = entry.lock()?;
41 f(path)?;
42 Ok(())
43 }
44 pub fn with_sync_abs_path(
46 &self,
47 path: &AbsolutePath,
48 mut f: impl FnMut(&AbsolutePath) -> Result<()>,
49 ) -> Result<()> {
50 {
51 let entry = {
53 let locks = self.locks.clone();
54 let mut locks = locks.write()?;
55 locks
56 .entry(path.to_path_buf())
57 .or_insert_with(|| Arc::new(Mutex::new(())))
58 .clone()
59 };
60 let _guard = entry.lock()?;
61 f(path)?;
62 }
63
64 Ok(())
65 }
66}
67
68pub type PathSyncSingleton = Arc<Mutex<PathSync>>;