zagens_tools/
resource_locks.rs1use std::collections::HashSet;
4
5use crate::dag_scheduler::ScheduleResource;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
9pub enum ResourceLockMode {
10 Shared,
11 Exclusive,
12}
13
14#[must_use]
16pub fn resource_lock_order(resource: &ScheduleResource) -> (u8, String) {
17 match resource {
18 ScheduleResource::WorkspaceScan => (0, String::new()),
19 ScheduleResource::Path(path) => (1, path.clone()),
20 ScheduleResource::WorkspaceWrite => (2, String::new()),
21 }
22}
23
24#[must_use]
26pub fn resource_lock_targets(
27 reads: &HashSet<ScheduleResource>,
28 writes: &HashSet<ScheduleResource>,
29) -> Vec<(ScheduleResource, ResourceLockMode)> {
30 let mut out: Vec<(ScheduleResource, ResourceLockMode)> = writes
31 .iter()
32 .map(|resource| (resource.clone(), ResourceLockMode::Exclusive))
33 .collect();
34 for resource in reads {
35 if !writes.contains(resource) {
36 out.push((resource.clone(), ResourceLockMode::Shared));
37 }
38 }
39 out.sort_by(|a, b| {
40 resource_lock_order(&a.0)
41 .cmp(&resource_lock_order(&b.0))
42 .then_with(|| a.1.cmp(&b.1))
43 });
44 out
45}
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50
51 #[test]
52 fn write_paths_are_exclusive_reads_shared() {
53 let reads = HashSet::from([
54 ScheduleResource::Path("a".to_string()),
55 ScheduleResource::WorkspaceScan,
56 ]);
57 let writes = HashSet::from([ScheduleResource::Path("a".to_string())]);
58 let targets = resource_lock_targets(&reads, &writes);
59 assert_eq!(targets.len(), 2);
60 assert!(
61 targets
62 .iter()
63 .any(|(r, m)| r == &ScheduleResource::Path("a".to_string())
64 && *m == ResourceLockMode::Exclusive)
65 );
66 assert!(
67 targets
68 .iter()
69 .any(|(r, m)| r == &ScheduleResource::WorkspaceScan
70 && *m == ResourceLockMode::Shared)
71 );
72 }
73
74 #[test]
75 fn distinct_read_paths_yield_two_shared_targets() {
76 let reads = HashSet::from([
77 ScheduleResource::Path("a".to_string()),
78 ScheduleResource::Path("b".to_string()),
79 ]);
80 let targets = resource_lock_targets(&reads, &HashSet::new());
81 assert_eq!(targets.len(), 2);
82 assert!(targets.iter().all(|(_, m)| *m == ResourceLockMode::Shared));
83 }
84}