1use crate::NodeId;
8use std::collections::HashMap;
9use std::sync::{Arc, Mutex};
10
11pub fn node_id_of_arc<T>(arc: &Arc<Mutex<T>>) -> NodeId {
24 NodeId(Arc::as_ptr(arc) as *const () as usize)
25}
26
27pub fn collect_nodes_arc<T, F>(root: &Arc<Mutex<T>>, children: &F) -> HashMap<NodeId, Arc<Mutex<T>>>
45where
46 F: Fn(&T) -> Vec<Arc<Mutex<T>>>,
47{
48 let mut visited = HashMap::new();
49 collect_inner(root, children, &mut visited);
50 visited
51}
52
53fn collect_inner<T, F>(
54 node: &Arc<Mutex<T>>,
55 children: &F,
56 visited: &mut HashMap<NodeId, Arc<Mutex<T>>>,
57) where
58 F: Fn(&T) -> Vec<Arc<Mutex<T>>>,
59{
60 let id = node_id_of_arc(node);
61 if visited.contains_key(&id) {
62 return;
63 }
64 visited.insert(id, node.clone());
65
66 let kids = children(&node.lock().expect("mutex should not be poisoned"));
67 for kid in &kids {
68 collect_inner(kid, children, visited);
69 }
70}
71
72pub fn reify_graph_arc<T, F>(root: Arc<Mutex<T>>, children: F) -> crate::ReifiedGraph<T>
97where
98 F: Fn(&T) -> Vec<Arc<Mutex<T>>>,
99 T: Clone,
100{
101 let all_nodes = collect_nodes_arc(&root, &children);
102 let root_id = node_id_of_arc(&root);
103
104 let mut nodes = Vec::with_capacity(all_nodes.len());
105 let mut edges = Vec::new();
106
107 for (id, arc) in &all_nodes {
108 let guard = arc.lock().expect("mutex should not be poisoned");
109 nodes.push((*id, guard.clone()));
110
111 for kid in children(&guard) {
112 let kid_id = node_id_of_arc(&kid);
113 edges.push((*id, kid_id));
114 }
115 }
116
117 crate::ReifiedGraph {
118 nodes,
119 edges,
120 root: root_id,
121 }
122}
123
124pub fn reflect_graph_arc<T, F>(graph: crate::ReifiedGraph<T>, set_children: F) -> Arc<Mutex<T>>
146where
147 F: Fn(&mut T, Vec<Arc<Mutex<T>>>),
148 T: Clone,
149{
150 let mut arc_map: HashMap<NodeId, Arc<Mutex<T>>> = HashMap::new();
151 for (id, data) in &graph.nodes {
152 arc_map.insert(*id, Arc::new(Mutex::new(data.clone())));
153 }
154
155 let mut adj: HashMap<NodeId, Vec<NodeId>> = HashMap::new();
156 for (from, to) in &graph.edges {
157 adj.entry(*from).or_default().push(*to);
158 }
159
160 for (id, arc) in &arc_map {
161 if let Some(child_ids) = adj.get(id) {
162 let kids: Vec<Arc<Mutex<T>>> =
163 child_ids.iter().map(|cid| arc_map[cid].clone()).collect();
164 set_children(&mut arc.lock().expect("mutex should not be poisoned"), kids);
165 }
166 }
167
168 arc_map[&graph.root].clone()
169}
170
171#[cfg(test)]
172mod tests {
173 use super::*;
174
175 #[derive(Clone, Debug)]
176 struct Node {
177 #[allow(dead_code)]
178 value: i32,
179 children: Vec<Arc<Mutex<Node>>>,
180 }
181
182 fn children_of(n: &Node) -> Vec<Arc<Mutex<Node>>> {
183 n.children.clone()
184 }
185
186 fn set_children_of(n: &mut Node, kids: Vec<Arc<Mutex<Node>>>) {
187 n.children = kids;
188 }
189
190 #[test]
191 fn arc_node_id_identity() {
192 let a = Arc::new(Mutex::new(Node {
193 value: 1,
194 children: vec![],
195 }));
196 let b = a.clone();
197 assert_eq!(node_id_of_arc(&a), node_id_of_arc(&b));
198
199 let c = Arc::new(Mutex::new(Node {
200 value: 1,
201 children: vec![],
202 }));
203 assert_ne!(node_id_of_arc(&a), node_id_of_arc(&c));
204 }
205
206 #[test]
207 fn arc_round_trip_preserves_sharing() {
208 let shared = Arc::new(Mutex::new(Node {
209 value: 42,
210 children: vec![],
211 }));
212 let root = Arc::new(Mutex::new(Node {
213 value: 0,
214 children: vec![shared.clone(), shared.clone()],
215 }));
216
217 let graph = reify_graph_arc(root, children_of);
218 let rebuilt = reflect_graph_arc(graph, set_children_of);
219
220 let children = rebuilt.lock().unwrap().children.clone();
221 assert_eq!(children.len(), 2);
222 assert_eq!(
223 Arc::as_ptr(&children[0]) as usize,
224 Arc::as_ptr(&children[1]) as usize
225 );
226 }
227
228 #[test]
229 fn arc_cycle_detection() {
230 let a = Arc::new(Mutex::new(Node {
231 value: 0,
232 children: vec![],
233 }));
234 let b = Arc::new(Mutex::new(Node {
235 value: 1,
236 children: vec![a.clone()],
237 }));
238 a.lock().unwrap().children.push(b.clone());
239
240 let nodes = collect_nodes_arc(&a, &children_of);
241 assert_eq!(nodes.len(), 2);
242 }
243}