1#[cfg(test)]
2pub mod tests;
3
4use dashmap::mapref::entry::Entry;
5use dashmap::DashMap;
6use std::hash::Hash;
7use std::mem::ManuallyDrop;
8use std::ops::Deref;
9use std::sync::Arc;
10
11struct EntryInner<K: Clone + Eq + Hash, L: Default> {
12 key: K,
13 lock: L,
14}
15
16pub struct ArbitraryLockEntry<K: Clone + Eq + Hash, L: Default> {
17 inner: ManuallyDrop<Arc<EntryInner<K, L>>>,
19 map: ArbitraryLock<K, L>,
20}
21
22impl<K: Clone + Eq + Hash, L: Default> Drop for ArbitraryLockEntry<K, L> {
23 fn drop(&mut self) {
24 let key = self.inner.key.clone();
25 unsafe {
27 ManuallyDrop::drop(&mut self.inner);
28 };
29 let Entry::Occupied(mut e) = self.map.map.entry(key) else {
30 return;
32 };
33 let arc = e.get_mut().take().unwrap();
34 match Arc::try_unwrap(arc) {
36 Ok(_) => {
37 e.remove();
39 }
40 Err(arc) => {
41 *e.get_mut() = Some(arc);
43 }
44 };
45 }
46}
47
48impl<K: Clone + Eq + Hash, L: Default> Deref for ArbitraryLockEntry<K, L> {
49 type Target = L;
50
51 fn deref(&self) -> &Self::Target {
52 &self.inner.lock
53 }
54}
55
56pub struct ArbitraryLock<K: Clone + Eq + Hash, L: Default> {
59 map: Arc<DashMap<K, Option<Arc<EntryInner<K, L>>>, ahash::RandomState>>,
60}
61
62impl<K: Clone + Hash + Eq, L: Default> ArbitraryLock<K, L> {
63 pub fn new() -> Self {
64 Self {
65 map: Default::default(),
66 }
67 }
68
69 pub fn get(&self, k: K) -> ArbitraryLockEntry<K, L> {
70 let inner = self
71 .map
72 .entry(k.clone())
73 .or_insert_with(|| {
74 Some(Arc::new(EntryInner {
75 key: k,
76 lock: L::default(),
77 }))
78 })
79 .clone()
80 .unwrap();
82 ArbitraryLockEntry {
83 inner: ManuallyDrop::new(inner),
84 map: self.clone(),
85 }
86 }
87
88 pub fn len(&self) -> usize {
89 self.map.len()
90 }
91
92 pub fn is_empty(&self) -> bool {
93 self.map.is_empty()
94 }
95
96 pub fn capacity(&self) -> usize {
97 self.map.capacity()
98 }
99
100 pub fn shrink_to_fit(&self) {
101 self.map.shrink_to_fit();
102 }
103}
104
105impl<K: Clone + Hash + Eq, L: Default> Clone for ArbitraryLock<K, L> {
106 fn clone(&self) -> Self {
107 Self {
108 map: self.map.clone(),
109 }
110 }
111}