tracing_rc/sync/
trace.rs

1use crate::sync::GcVisitor;
2
3/// The `Sync` version of the [`rc::Trace`](crate::rc::Trace) trait.
4pub trait Trace: Send + Sync {
5    /// Visit the children of this type. The implementation should call `visit_children` on each
6    /// owned value which implements [`Trace`].
7    fn visit_children(&self, visitor: &mut GcVisitor);
8}
9
10/// Implements a no-op [`Trace`] for a type.
11///
12/// This will cause memory leaks if it is used to implement tracing on a type which ends up
13/// participating in a cycle. This is useful for types that are e.g. used as a key in
14/// [`std::collections::HashMap`], but are not actually `Agc` pointers.
15#[macro_export]
16macro_rules! sync_empty_trace {
17    ($t:path) => {
18        impl $crate::sync::Trace for $t {
19            #[inline]
20            fn visit_children(&self, _: &mut $crate::sync::GcVisitor) {}
21        }
22    };
23    ($first:path, $($rest:path),+) => {
24        sync_empty_trace!($first);
25        sync_empty_trace!($($rest),+);
26    };
27}
28
29sync_empty_trace!(f32, f64);
30sync_empty_trace!(i8, i16, i32, i64, isize, i128);
31sync_empty_trace!(u8, u16, u32, u64, usize, u128);
32sync_empty_trace!(bool, char);
33sync_empty_trace!(std::string::String);
34
35impl Trace for () {
36    fn visit_children(&self, _: &mut GcVisitor) {}
37}
38
39impl<T: Trace> Trace for std::option::Option<T> {
40    fn visit_children(&self, visitor: &mut GcVisitor) {
41        if let Some(inner) = self {
42            inner.visit_children(visitor);
43        }
44    }
45}
46
47impl<T: Trace> Trace for std::vec::Vec<T> {
48    fn visit_children(&self, visitor: &mut GcVisitor) {
49        for elem in self.iter() {
50            elem.visit_children(visitor);
51        }
52    }
53}
54
55impl<T: Trace> Trace for std::boxed::Box<T> {
56    fn visit_children(&self, visitor: &mut GcVisitor) {
57        T::visit_children(self, visitor);
58    }
59}
60
61impl<T: Trace, const S: usize> Trace for [T; S] {
62    fn visit_children(&self, visitor: &mut GcVisitor) {
63        for elem in self.iter() {
64            elem.visit_children(visitor);
65        }
66    }
67}
68
69impl<T: Trace> Trace for [T] {
70    fn visit_children(&self, visitor: &mut GcVisitor) {
71        for elem in self.iter() {
72            elem.visit_children(visitor);
73        }
74    }
75}
76
77impl<V: Trace> Trace for std::collections::BinaryHeap<V> {
78    fn visit_children(&self, visitor: &mut GcVisitor) {
79        for v in self.iter() {
80            v.visit_children(visitor);
81        }
82    }
83}
84
85impl<K: Trace, V: Trace> Trace for std::collections::BTreeMap<K, V> {
86    fn visit_children(&self, visitor: &mut GcVisitor) {
87        for (k, v) in self.iter() {
88            k.visit_children(visitor);
89            v.visit_children(visitor);
90        }
91    }
92}
93
94impl<V: Trace> Trace for std::collections::BTreeSet<V> {
95    fn visit_children(&self, visitor: &mut GcVisitor) {
96        for v in self.iter() {
97            v.visit_children(visitor);
98        }
99    }
100}
101
102impl<K: Trace, V: Trace, S: std::hash::BuildHasher + Send + Sync> Trace
103    for std::collections::HashMap<K, V, S>
104{
105    fn visit_children(&self, visitor: &mut GcVisitor) {
106        for (k, v) in self.iter() {
107            k.visit_children(visitor);
108            v.visit_children(visitor);
109        }
110    }
111}
112
113impl<V: Trace, S: std::hash::BuildHasher + Send + Sync> Trace for std::collections::HashSet<V, S> {
114    fn visit_children(&self, visitor: &mut GcVisitor) {
115        for v in self.iter() {
116            v.visit_children(visitor);
117        }
118    }
119}
120
121impl<V: Trace> Trace for std::collections::LinkedList<V> {
122    fn visit_children(&self, visitor: &mut GcVisitor) {
123        for v in self.iter() {
124            v.visit_children(visitor);
125        }
126    }
127}
128
129impl<V: Trace> Trace for std::collections::VecDeque<V> {
130    fn visit_children(&self, visitor: &mut GcVisitor) {
131        for v in self.iter() {
132            v.visit_children(visitor);
133        }
134    }
135}
136
137impl<T: Trace> Trace for std::sync::Mutex<T> {
138    fn visit_children(&self, visitor: &mut GcVisitor) {
139        if let Ok(guard) = self.try_lock() {
140            guard.visit_children(visitor);
141        }
142    }
143}
144
145impl<T: Trace> Trace for std::sync::RwLock<T> {
146    fn visit_children(&self, visitor: &mut GcVisitor) {
147        if let Ok(guard) = self.try_read() {
148            guard.visit_children(visitor);
149        }
150    }
151}