weak_lists/sync.rs
1//! The thread-safe version of the list.
2
3mod element;
4mod iter;
5mod list;
6#[cfg(test)]
7mod tests;
8
9use {
10 alloc::sync::{Arc, Weak},
11 core::ops::Range,
12 parking_lot::Mutex,
13 stable_map::StableMap,
14};
15
16/// A thread-safe list holding weak references to its elements.
17///
18/// The list does not hold strong references to its elements and the elements do not hold
19/// strong references to the list. You must use some other mechanism to keep all parties
20/// alive.
21///
22/// This list supports concurrent iteration and modification.
23///
24/// # Examples
25///
26/// ```
27/// use std::sync::Arc;
28/// use {
29/// weak_lists::{SyncWeakList, SyncWeakListElement},
30/// std::{
31/// array,
32/// },
33/// };
34///
35/// pub struct Service {
36/// callbacks: SyncWeakList<dyn Callback>,
37/// }
38///
39/// pub trait Callback {
40/// fn run(&self);
41/// }
42///
43/// impl Service {
44/// pub fn register_callback(&self, callback: &SyncWeakListElement<dyn Callback>) {
45/// callback.attach(&self.callbacks);
46/// }
47///
48/// pub fn run_callbacks(&self) {
49/// for callback in &self.callbacks {
50/// callback.run();
51/// }
52/// }
53/// }
54///
55/// struct Client {
56/// id: usize,
57/// entry: SyncWeakListElement<dyn Callback>,
58/// }
59///
60/// impl Callback for Client {
61/// fn run(&self) {
62/// eprintln!("Callback {} invoked", self.id);
63/// if self.id == 1 {
64/// self.entry.detach();
65/// }
66/// }
67/// }
68///
69/// let service = Service {
70/// callbacks: Default::default(),
71/// };
72/// let clients = array::from_fn::<_, 3, _>(|id| {
73/// Arc::<Client>::new_cyclic(|slf| Client {
74/// id,
75/// entry: SyncWeakListElement::new(slf.clone()),
76/// })
77/// });
78/// for client in &clients {
79/// service.register_callback(&client.entry);
80/// }
81/// service.run_callbacks();
82/// // Callback 0 invoked
83/// // Callback 1 invoked
84/// // Callback 2 invoked
85/// service.run_callbacks();
86/// // Callback 0 invoked
87/// // Callback 2 invoked
88/// ```
89pub struct SyncWeakList<T>
90where
91 T: ?Sized,
92{
93 data: Arc<Mutex<WeakListData<T>>>,
94}
95
96struct WeakListData<T>
97where
98 T: ?Sized,
99{
100 next_id: u64,
101 active_iterators: usize,
102 members: StableMap<u64, Weak<T>>,
103}
104
105/// An thread-safe element that can be inserted into a weak list.
106///
107/// Each element can be attached to 0 or 1 list. Attaching it to a list automatically
108/// detaches itself from the previous list.
109///
110/// When this object is dropped, it detaches itself from its current list.
111pub struct SyncWeakListElement<T>
112where
113 T: ?Sized,
114{
115 t: Weak<T>,
116 data: Mutex<EntryData<T>>,
117}
118
119struct EntryData<T>
120where
121 T: ?Sized,
122{
123 id: u64,
124 owner: Weak<Mutex<WeakListData<T>>>,
125}
126
127/// An iterator over list elements.
128///
129/// This object is created by calling [iter](SyncWeakList::iter) or by using the
130/// [IntoIterator] implementation of `&SyncWeakList`.
131pub struct Iter<'a, T>
132where
133 T: ?Sized,
134{
135 iter: Range<usize>,
136 data: &'a Mutex<WeakListData<T>>,
137}