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