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}