use std::collections::HashMap; use std::sync::Arc; pub trait RefCountValue { fn did_remove(&self) {} } struct RefCountHandler { ref_count: usize, inner: T, } impl RefCountHandler { pub fn new(inner: T) -> Self { Self { ref_count: 1, inner } } pub fn increase_ref_count(&mut self) { self.ref_count += 1; } } pub struct RefCountHashMap(HashMap>); impl std::default::Default for RefCountHashMap { fn default() -> Self { Self(HashMap::new()) } } impl RefCountHashMap where T: Clone + Send + Sync + RefCountValue, { pub fn new() -> Self { Self::default() } pub fn get(&self, key: &str) -> Option { self.0.get(key).map(|handler| handler.inner.clone()) } pub fn values(&self) -> Vec { self.0.values().map(|value| value.inner.clone()).collect::>() } pub fn insert(&mut self, key: String, value: T) { if let Some(handler) = self.0.get_mut(&key) { handler.increase_ref_count(); } else { let handler = RefCountHandler::new(value); self.0.insert(key, handler); } } pub fn remove(&mut self, key: &str) { let mut should_remove = false; if let Some(value) = self.0.get_mut(key) { if value.ref_count > 0 { value.ref_count -= 1; } should_remove = value.ref_count == 0; } if should_remove { if let Some(handler) = self.0.remove(key) { handler.inner.did_remove(); } } } } impl RefCountValue for Arc where T: RefCountValue, { fn did_remove(&self) { (**self).did_remove() } }