kumo_server_common/
hashable_weak.rs1use std::hash::{Hash, Hasher};
2use std::sync::{Arc, Weak};
3
4pub struct HashableWeak<T: ?Sized>(pub Weak<T>);
17
18impl<T: ?Sized> HashableWeak<T> {
19 pub fn new(arc: &Arc<T>) -> Self {
20 Self(Arc::downgrade(arc))
21 }
22}
23
24impl<T> Hash for HashableWeak<T> {
25 fn hash<H: Hasher>(&self, state: &mut H) {
26 (self.0.as_ptr() as usize).hash(state)
27 }
28}
29
30impl<T: ?Sized> PartialEq for HashableWeak<T> {
31 fn eq(&self, other: &Self) -> bool {
32 Weak::ptr_eq(&self.0, &other.0)
33 }
34}
35
36impl<T: ?Sized> Eq for HashableWeak<T> {}
37
38impl<T: ?Sized> Clone for HashableWeak<T> {
39 fn clone(&self) -> Self {
40 Self(self.0.clone())
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47 use std::collections::HashSet;
48
49 #[test]
50 fn dedup_by_pointer_identity() {
51 let a = Arc::new(42u32);
52 let b = Arc::new(42u32);
53 let mut set: HashSet<HashableWeak<u32>> = HashSet::new();
54 set.insert(HashableWeak::new(&a));
55 set.insert(HashableWeak::new(&a));
56 set.insert(HashableWeak::new(&b));
57 assert_eq!(set.len(), 2);
58 }
59
60 #[test]
61 fn prune_via_upgrade() {
62 let a = Arc::new(42u32);
63 let mut set: HashSet<HashableWeak<u32>> = HashSet::new();
64 set.insert(HashableWeak::new(&a));
65 drop(a);
66 set.retain(|hw| hw.0.upgrade().is_some());
67 assert_eq!(set.len(), 0);
68 }
69
70 #[test]
71 fn iter_upgrade_collects_live() {
72 let a = Arc::new(1u32);
73 let b = Arc::new(2u32);
74 let mut set: HashSet<HashableWeak<u32>> = HashSet::new();
75 set.insert(HashableWeak::new(&a));
76 set.insert(HashableWeak::new(&b));
77 drop(a);
78 let live: Vec<u32> = set
79 .iter()
80 .filter_map(|hw| hw.0.upgrade().map(|v| *v))
81 .collect();
82 assert_eq!(live, vec![2]);
83 }
84}