weak_lists/unsync/element.rs
1use {
2 crate::unsync::{EntryData, WeakList, WeakListElement},
3 alloc::rc::{Rc, Weak},
4 core::{
5 cell::UnsafeCell,
6 fmt::{Debug, Formatter},
7 mem,
8 },
9};
10
11impl<T> WeakListElement<T>
12where
13 T: ?Sized,
14{
15 /// Creates a new list element.
16 ///
17 /// This object holds a weak reference to the `T`. When this object is dropped, it
18 /// automatically detaches itself from the list it is currently attached to.
19 ///
20 /// Often, this object is directly contained in the `T`:
21 ///
22 /// ```rust
23 /// use std::rc::Rc;
24 /// use weak_lists::WeakListElement;
25 ///
26 /// struct Client {
27 /// element: WeakListElement<Client>,
28 /// }
29 ///
30 /// let client = Rc::new_cyclic(|slf| Client {
31 /// element: WeakListElement::new(slf.clone()),
32 /// });
33 /// ```
34 ///
35 /// Since only weak references are stored, this does not create any actual reference
36 /// cycles.
37 pub fn new(t: Weak<T>) -> Self {
38 Self {
39 t,
40 data: UnsafeCell::new(EntryData {
41 id: 0,
42 owner: Default::default(),
43 }),
44 }
45 }
46
47 /// Attaches the list element to a list.
48 ///
49 /// If this object was previously attached to a list, it is automatically detached
50 /// from that list.
51 ///
52 /// The list will only hold on a weak reference to this element and vice versa.
53 ///
54 /// Any existing iterator over the list might or might not see this element, this is
55 /// unspecified.
56 ///
57 /// # Examples
58 ///
59 /// ```rust
60 /// use std::rc::Rc;
61 /// use weak_lists::{WeakList, WeakListElement};
62 ///
63 /// struct Client {
64 /// element: WeakListElement<Client>,
65 /// }
66 ///
67 /// let clients1 = WeakList::default();
68 ///
69 /// let client = Rc::new_cyclic(|slf| Client {
70 /// element: WeakListElement::new(slf.clone()),
71 /// });
72 ///
73 /// client.element.attach(&clients1);
74 ///
75 /// assert!(clients1.iter().next().is_some());
76 ///
77 /// let clients2 = WeakList::default();
78 ///
79 /// client.element.attach(&clients2);
80 ///
81 /// assert!(clients1.iter().next().is_none());
82 /// assert!(clients2.iter().next().is_some());
83 /// ```
84 pub fn attach(&self, to: &WeakList<T>) {
85 self.detach();
86 let data = unsafe {
87 // SAFETY:
88 // - While we hold this reference, we do not call any functions that might
89 // create additional references to self.data. This applies to all code that
90 // creates references to self.data.
91 // - Therefore, this is an exclusive reference to self.data.
92 // - In particular, the clone call below clones an Rc and is therefore safe.
93 // - The insert call only adds an element to a map and is therefore safe.
94 // - list_data.next_id cannot overflow, therefore the insert call returns none
95 // and no drop code runs. But even if it did run, it would run after all
96 // uses of the mutable references have concluded.
97 &mut *self.data.get()
98 };
99 data.owner = Rc::downgrade(&to.data);
100 let list_data = unsafe {
101 // SAFETY: See the previous safety comment.
102 &mut *to.data.get()
103 };
104 data.id = list_data.next_id;
105 list_data.next_id += 1;
106 list_data.members.insert(data.id, self.t.clone());
107 }
108
109 /// Detaches the element from its current list.
110 ///
111 /// # Examples
112 ///
113 /// ```rust
114 /// use std::rc::Rc;
115 /// use weak_lists::{WeakList, WeakListElement};
116 ///
117 /// struct Client {
118 /// element: WeakListElement<Client>,
119 /// }
120 ///
121 /// let clients = WeakList::default();
122 ///
123 /// let client = Rc::new_cyclic(|slf| Client {
124 /// element: WeakListElement::new(slf.clone()),
125 /// });
126 ///
127 /// client.element.attach(&clients);
128 ///
129 /// assert!(clients.iter().next().is_some());
130 ///
131 /// client.element.detach();
132 ///
133 /// assert!(clients.iter().next().is_none());
134 /// ```
135 pub fn detach(&self) {
136 let data = unsafe {
137 // SAFETY:
138 // - While we hold this reference, we do not call any functions that might
139 // create additional references to self.data. This applies to all code that
140 // creates references to self.data.
141 // - Therefore, this is an exclusive reference to self.data.
142 // - All drop code below runs after the last use of the references has
143 // concluded. However, even if it did run, it could be shown that that code
144 // is harmless and does not run any code that depends on T.
145 &mut *self.data.get()
146 };
147 let prev = mem::take(&mut data.owner).upgrade();
148 if let Some(prev) = prev {
149 let list_data = unsafe {
150 // SAFETY: See the previous safety comment.
151 &mut *prev.get()
152 };
153 list_data.members.remove(&data.id);
154 }
155 }
156}
157
158impl<T> Drop for WeakListElement<T>
159where
160 T: ?Sized,
161{
162 fn drop(&mut self) {
163 self.detach();
164 }
165}
166
167impl<T> Debug for WeakListElement<T>
168where
169 T: ?Sized,
170{
171 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
172 let data = unsafe {
173 // SAFETY:
174 // - While we hold this reference, we do not call any functions that might
175 // create additional references to self.data. This applies to all code that
176 // creates references to self.data.
177 // - Therefore, this is an exclusive reference to self.data.
178 &mut *self.data.get()
179 };
180 let owner = data.owner.upgrade();
181 let owner_id = owner.as_ref().map(Rc::as_ptr);
182 f.debug_struct("WeakListElement")
183 .field("list", &owner_id)
184 .finish_non_exhaustive()
185 }
186}