xvc_walker/
sync.rs

1//! This module contains PathSync structure to synchronize operations on paths.
2use std::{
3    collections::HashMap,
4    path::{Path, PathBuf},
5    sync::{Arc, Mutex, RwLock},
6};
7
8use crate::{AbsolutePath, Result};
9
10/// When multiple threads try to access the same path (especially in cache operations) we get weird
11/// race conditions, This structure is to make those operations atomic and thread safe.
12#[derive(Debug, Default)]
13pub struct PathSync {
14    locks: Arc<RwLock<HashMap<PathBuf, Arc<Mutex<()>>>>>,
15}
16
17impl PathSync {
18    /// Create a new PathSync
19    pub fn new() -> Self {
20        Self {
21            locks: Arc::new(RwLock::new(HashMap::new())),
22        }
23    }
24
25    /// Locks the path and runs the given closure with it.
26    pub fn with_sync_path(
27        &self,
28        path: &Path,
29        mut f: impl FnMut(&Path) -> Result<()>,
30    ) -> Result<()> {
31        // Do not lock the whole HashMap
32        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    /// Locks the path and runs the given closure with it.
45    pub fn with_sync_abs_path(
46        &self,
47        path: &AbsolutePath,
48        mut f: impl FnMut(&AbsolutePath) -> Result<()>,
49    ) -> Result<()> {
50        {
51            // Do not lock the whole HashMap
52            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
68/// A thread safe singleton for PathSync
69pub type PathSyncSingleton = Arc<Mutex<PathSync>>;