1use fuchsia_sync::RwLock;
6use std::borrow::Borrow;
7use std::collections::hash_map::Entry;
8use std::collections::HashMap;
9use std::hash::Hash;
10use std::sync::atomic::{AtomicBool, Ordering};
11use std::sync::{Arc, Weak};
12
13pub struct DetachableWeak<K, V> {
18 inner: Weak<V>,
21 parent: Arc<RwLock<HashMap<K, (Arc<V>, Arc<AtomicBool>)>>>,
22 key_ref: Arc<AtomicBool>,
26 key: K,
28}
29
30impl<K: Clone, V> Clone for DetachableWeak<K, V> {
31 fn clone(&self) -> Self {
32 Self {
33 inner: self.inner.clone(),
34 parent: self.parent.clone(),
35 key_ref: self.key_ref.clone(),
36 key: self.key.clone(),
37 }
38 }
39}
40
41impl<K: Hash + Eq, V> DetachableWeak<K, V> {
42 fn new(
43 item: &Arc<V>,
44 parent: Arc<RwLock<HashMap<K, (Arc<V>, Arc<AtomicBool>)>>>,
45 key: K,
46 key_ref: Arc<AtomicBool>,
47 ) -> Self {
48 Self { inner: Arc::downgrade(item), parent, key, key_ref }
49 }
50
51 pub fn upgrade(&self) -> Option<Arc<V>> {
54 self.inner.upgrade()
55 }
56
57 pub fn detach(self) {
61 let mut lock = self.parent.write();
62 if self.key_ref.swap(false, Ordering::Relaxed) {
63 let _ = lock.remove(&self.key);
66 }
67 }
68
69 pub fn key(&self) -> &K {
71 &self.key
72 }
73}
74
75pub struct LazyEntry<K, V> {
76 parent: Arc<RwLock<HashMap<K, (Arc<V>, Arc<AtomicBool>)>>>,
77 key: K,
78}
79
80impl<K: Clone, V> Clone for LazyEntry<K, V> {
81 fn clone(&self) -> Self {
82 Self { parent: self.parent.clone(), key: self.key.clone() }
83 }
84}
85
86impl<K: Hash + Eq + Clone, V> LazyEntry<K, V> {
87 fn new(parent: Arc<RwLock<HashMap<K, (Arc<V>, Arc<AtomicBool>)>>>, key: K) -> Self {
88 Self { parent, key }
89 }
90
91 pub fn key(&self) -> &K {
93 &self.key
94 }
95
96 pub fn try_insert(&self, value: V) -> Result<DetachableWeak<K, V>, V> {
100 match self.parent.write().entry(self.key.clone()) {
101 Entry::Occupied(_) => return Err(value),
102 Entry::Vacant(entry) => {
103 let _ = entry.insert((Arc::new(value), Arc::new(AtomicBool::new(true))));
104 }
105 };
106 Ok(self.get().unwrap())
107 }
108
109 pub fn get(&self) -> Option<DetachableWeak<K, V>> {
112 self.parent.read().get(&self.key).and_then(|(v, key_ref)| {
113 let map = self.parent.clone();
114 let key_ref = key_ref.clone();
115 let key = self.key.clone();
116 Some(DetachableWeak::new(&v, map, key, key_ref))
117 })
118 }
119}
120
121pub struct DetachableMap<K, V> {
125 map: Arc<RwLock<HashMap<K, (Arc<V>, Arc<AtomicBool>)>>>,
128}
129
130impl<K: Hash + Eq + Clone, V> Default for DetachableMap<K, V> {
131 fn default() -> Self {
132 Self { map: Arc::new(RwLock::new(HashMap::new())) }
133 }
134}
135
136impl<K: Hash + Eq + Clone, V> DetachableMap<K, V> {
137 pub fn new() -> DetachableMap<K, V> {
139 Default::default()
140 }
141
142 pub fn insert(&mut self, key: K, value: V) -> Option<Arc<V>> {
145 let mut lock = self.map.write();
146 let new_pair = (Arc::new(value), Arc::new(AtomicBool::new(true)));
147 if let Some((prev_val, old_key_ref)) = lock.insert(key, new_pair) {
148 old_key_ref.store(false, Ordering::Relaxed);
149 Some(prev_val)
150 } else {
151 None
152 }
153 }
154
155 pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
158 where
159 K: Borrow<Q>,
160 Q: Hash + Eq,
161 {
162 self.map.read().contains_key(key)
163 }
164
165 pub fn get(&self, key: &K) -> Option<DetachableWeak<K, V>> {
167 self.map.read().get(key).and_then(|(v, key_ref)| {
168 let map = self.map.clone();
169 let key_ref = key_ref.clone();
170 let key = key.clone();
171 Some(DetachableWeak::new(&v, map, key, key_ref))
172 })
173 }
174
175 pub fn lazy_entry(&self, key: &K) -> LazyEntry<K, V> {
180 LazyEntry::new(self.map.clone(), key.clone())
181 }
182}
183
184#[cfg(test)]
185mod test {
186 use super::*;
187
188 #[derive(Default, Debug, PartialEq)]
189 struct TestStruct {
190 data: u32,
191 }
192
193 #[test]
194 fn contains_keys() {
195 let mut map = DetachableMap::default();
196
197 assert!(map.insert(0, TestStruct { data: 45 }).is_none());
198
199 assert!(map.contains_key(&0));
200
201 let detached = map.get(&0);
202 assert!(detached.is_some());
203 detached.unwrap().detach();
205
206 assert_eq!(false, map.contains_key(&0));
207 }
208
209 #[test]
210 fn upgrade_detached() {
211 let mut map = DetachableMap::default();
212
213 assert!(map.insert(0, TestStruct { data: 45 }).is_none());
214
215 let detached = map.get(&0);
216 assert!(detached.is_some());
217 let detached = detached.unwrap();
218 let detached_clone = detached.clone();
219
220 let second = map.get(&0);
221 assert!(second.is_some());
222 let second = second.unwrap();
223
224 let upgraded = detached.upgrade().expect("should be able to upgrade");
225
226 second.detach();
228
229 assert!(map.get(&0).is_none());
230
231 let second_up = detached.upgrade().expect("should be able to upgrade");
233 let third_up = detached_clone.upgrade().expect("should be able to upgrade");
234
235 drop(upgraded);
237 drop(second_up);
238 drop(third_up);
239
240 assert!(detached.upgrade().is_none());
241
242 detached.detach();
244 }
245
246 #[test]
247 fn cant_detach_replaced_key() {
248 let mut map = DetachableMap::default();
249
250 assert!(map.insert(0, TestStruct { data: 12 }).is_none());
251
252 let detached = map.get(&0).expect("key is in");
253
254 let replaced = map.insert(0, TestStruct { data: 34 });
256
257 assert_eq!(TestStruct { data: 12 }, *detached.upgrade().expect("data is still alive"));
259
260 drop(replaced);
262
263 assert!(detached.upgrade().is_none());
264
265 detached.detach();
267
268 let new_detached = map.get(&0).expect("key was replaced");
269
270 assert_eq!(TestStruct { data: 34 }, *new_detached.upgrade().expect("should be there"));
271
272 let cloned = new_detached.clone();
274 let another = map.get(&0).expect("still there");
275
276 new_detached.detach();
277
278 assert!(map.get(&0).is_none());
279
280 let replaced = map.insert(0, TestStruct { data: 45 });
282 assert!(replaced.is_none());
283
284 cloned.detach();
286 assert!(map.get(&0).is_some());
287 another.detach();
289 assert!(map.get(&0).is_some());
290 }
291
292 #[test]
293 fn lazy_entry() {
294 let map = DetachableMap::default();
295
296 let entry = map.lazy_entry(&1);
298
299 assert!(entry.get().is_none());
301
302 let detachable =
304 entry.try_insert(TestStruct { data: 45 }).expect("should be able to insert");
305
306 let second_val = TestStruct { data: 56 };
308 let returned_val =
309 entry.try_insert(second_val).err().expect("should get an error when trying to insert");
310 assert_eq!(56, returned_val.data);
311
312 assert!(entry.get().is_some());
313
314 detachable.detach();
316
317 assert!(entry.get().is_none());
318
319 let new = entry.try_insert(returned_val).expect("should be able to insert after removal");
320
321 drop(new);
323
324 let still_there = map.get(&1).expect("should be there");
325 assert!(still_there.upgrade().is_some());
326 }
327}