weak_lists/sync/element.rs
1use {
2 crate::sync::{EntryData, SyncWeakList, SyncWeakListElement},
3 alloc::sync::{Arc, Weak},
4 core::{
5 fmt::{Debug, Formatter},
6 mem,
7 },
8 parking_lot::Mutex,
9};
10
11impl<T> SyncWeakListElement<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::sync::Arc;
24 /// use weak_lists::SyncWeakListElement;
25 ///
26 /// struct Client {
27 /// element: SyncWeakListElement<Client>,
28 /// }
29 ///
30 /// let client = Arc::new_cyclic(|slf| Client {
31 /// element: SyncWeakListElement::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: Mutex::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::sync::Arc;
61 /// use weak_lists::{SyncWeakList, SyncWeakListElement};
62 ///
63 /// struct Client {
64 /// element: SyncWeakListElement<Client>,
65 /// }
66 ///
67 /// let clients1 = SyncWeakList::default();
68 ///
69 /// let client = Arc::new_cyclic(|slf| Client {
70 /// element: SyncWeakListElement::new(slf.clone()),
71 /// });
72 ///
73 /// client.element.attach(&clients1);
74 ///
75 /// assert!(clients1.iter().next().is_some());
76 ///
77 /// let clients2 = SyncWeakList::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: &SyncWeakList<T>) {
85 self.detach();
86 let data = &mut *self.data.lock();
87 data.owner = Arc::downgrade(&to.data);
88 let list_data = &mut *to.data.lock();
89 data.id = list_data.next_id;
90 list_data.next_id += 1;
91 list_data.members.insert(data.id, self.t.clone());
92 }
93
94 /// Detaches the element from its current list.
95 ///
96 /// # Examples
97 ///
98 /// ```rust
99 /// use std::rc::Rc;
100 /// use std::sync::Arc;
101 /// use weak_lists::{SyncWeakList, SyncWeakListElement};
102 ///
103 /// struct Client {
104 /// element: SyncWeakListElement<Client>,
105 /// }
106 ///
107 /// let clients = SyncWeakList::default();
108 ///
109 /// let client = Arc::new_cyclic(|slf| Client {
110 /// element: SyncWeakListElement::new(slf.clone()),
111 /// });
112 ///
113 /// client.element.attach(&clients);
114 ///
115 /// assert!(clients.iter().next().is_some());
116 ///
117 /// client.element.detach();
118 ///
119 /// assert!(clients.iter().next().is_none());
120 /// ```
121 pub fn detach(&self) {
122 let data = &mut *self.data.lock();
123 let prev = mem::take(&mut data.owner).upgrade();
124 if let Some(prev) = prev {
125 let list_data = &mut *prev.lock();
126 list_data.members.remove(&data.id);
127 }
128 }
129}
130
131impl<T> Drop for SyncWeakListElement<T>
132where
133 T: ?Sized,
134{
135 fn drop(&mut self) {
136 self.detach();
137 }
138}
139
140impl<T> Debug for SyncWeakListElement<T>
141where
142 T: ?Sized,
143{
144 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
145 let data = self.data.lock();
146 let owner = data.owner.upgrade();
147 let owner_id = owner.as_ref().map(Arc::as_ptr);
148 f.debug_struct("SyncWeakListElement")
149 .field("list", &owner_id)
150 .finish_non_exhaustive()
151 }
152}