#[cfg(test)]
pub mod tests;
use dashmap::mapref::entry::Entry;
use dashmap::DashMap;
use std::hash::Hash;
use std::mem::ManuallyDrop;
use std::ops::Deref;
use std::sync::Arc;
struct EntryInner<K: Clone + Eq + Hash, L: Default> {
key: K,
lock: L,
}
pub struct ArbitraryLockEntry<K: Clone + Eq + Hash, L: Default> {
inner: ManuallyDrop<Arc<EntryInner<K, L>>>,
map: ArbitraryLock<K, L>,
}
impl<K: Clone + Eq + Hash, L: Default> Drop for ArbitraryLockEntry<K, L> {
fn drop(&mut self) {
let key = self.inner.key.clone();
unsafe {
ManuallyDrop::drop(&mut self.inner);
};
let Entry::Occupied(mut e) = self.map.map.entry(key) else {
return;
};
let arc = e.get_mut().take().unwrap();
match Arc::try_unwrap(arc) {
Ok(_) => {
e.remove();
}
Err(arc) => {
*e.get_mut() = Some(arc);
}
};
}
}
impl<K: Clone + Eq + Hash, L: Default> Deref for ArbitraryLockEntry<K, L> {
type Target = L;
fn deref(&self) -> &Self::Target {
&self.inner.lock
}
}
pub struct ArbitraryLock<K: Clone + Eq + Hash, L: Default> {
map: Arc<DashMap<K, Option<Arc<EntryInner<K, L>>>, ahash::RandomState>>,
}
impl<K: Clone + Hash + Eq, L: Default> ArbitraryLock<K, L> {
pub fn new() -> Self {
Self {
map: Default::default(),
}
}
pub fn get(&self, k: K) -> ArbitraryLockEntry<K, L> {
let inner = self
.map
.entry(k.clone())
.or_insert_with(|| {
Some(Arc::new(EntryInner {
key: k,
lock: L::default(),
}))
})
.clone()
.unwrap();
ArbitraryLockEntry {
inner: ManuallyDrop::new(inner),
map: self.clone(),
}
}
pub fn len(&self) -> usize {
self.map.len()
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
pub fn capacity(&self) -> usize {
self.map.capacity()
}
pub fn shrink_to_fit(&self) {
self.map.shrink_to_fit();
}
}
impl<K: Clone + Hash + Eq, L: Default> Clone for ArbitraryLock<K, L> {
fn clone(&self) -> Self {
Self {
map: self.map.clone(),
}
}
}