Advertisement
Mivik

Untitled

Dec 12th, 2023 (edited)
978
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 3.91 KB | None | 0 0
  1. use dashmap::DashMap;
  2. use std::{
  3.     collections::BTreeSet,
  4.     hash::Hash,
  5.     mem::ManuallyDrop,
  6.     ops::{Deref, DerefMut},
  7.     sync::Arc,
  8. };
  9. use tokio::sync::{OwnedRwLockReadGuard, OwnedRwLockWriteGuard, RwLock};
  10.  
  11. pub trait Empty {
  12.     fn is_empty(&self) -> bool;
  13. }
  14.  
  15. impl Empty for () {
  16.     fn is_empty(&self) -> bool {
  17.         true
  18.     }
  19. }
  20.  
  21. impl<V> Empty for BTreeSet<V> {
  22.     fn is_empty(&self) -> bool {
  23.         BTreeSet::is_empty(self)
  24.     }
  25. }
  26.  
  27. type KeyLockInner<K, V> = Arc<DashMap<K, Arc<RwLock<V>>>>;
  28.  
  29. #[derive(Clone)]
  30. pub struct KeyLocks<K, V>(KeyLockInner<K, V>);
  31.  
  32. struct KeyRef<K, V> {
  33.     map: KeyLockInner<K, V>,
  34.     key: K,
  35. }
  36. impl<K: Eq + Hash, V: Empty> KeyRef<K, V> {
  37.     fn remove_if_needed<G: Deref<Target = V>>(&self, guard: &mut ManuallyDrop<G>) {
  38.         if guard.is_empty() {
  39.             self.map.remove_if(&self.key, |_, v| {
  40.                 unsafe { ManuallyDrop::drop(guard) };
  41.                 Arc::strong_count(v) == 1
  42.             });
  43.         } else {
  44.             unsafe { ManuallyDrop::drop(guard) };
  45.         }
  46.     }
  47. }
  48.  
  49. pub struct OwnedReadGuard<K: Eq + Hash, V: Empty> {
  50.     key: KeyRef<K, V>,
  51.     guard: ManuallyDrop<OwnedRwLockReadGuard<V>>,
  52. }
  53. impl<K: Eq + Hash, V: Empty> Deref for OwnedReadGuard<K, V> {
  54.     type Target = V;
  55.     fn deref(&self) -> &Self::Target {
  56.         self.guard.deref()
  57.     }
  58. }
  59. impl<K: Eq + Hash, V: Empty> Drop for OwnedReadGuard<K, V> {
  60.     fn drop(&mut self) {
  61.         self.key.remove_if_needed(&mut self.guard);
  62.     }
  63. }
  64.  
  65. pub struct OwnedWriteGuard<K: Eq + Hash, V: Empty> {
  66.     key: KeyRef<K, V>,
  67.     guard: ManuallyDrop<OwnedRwLockWriteGuard<V>>,
  68. }
  69. impl<K: Eq + Hash, V: Empty> Deref for OwnedWriteGuard<K, V> {
  70.     type Target = V;
  71.     fn deref(&self) -> &Self::Target {
  72.         self.guard.deref()
  73.     }
  74. }
  75.  
  76. impl<K: Eq + Hash, V: Empty> DerefMut for OwnedWriteGuard<K, V> {
  77.     fn deref_mut(&mut self) -> &mut Self::Target {
  78.         self.guard.deref_mut()
  79.     }
  80. }
  81.  
  82. impl<K: Eq + Hash, V: Empty> Drop for OwnedWriteGuard<K, V> {
  83.     fn drop(&mut self) {
  84.         self.key.remove_if_needed(&mut self.guard);
  85.     }
  86. }
  87.  
  88. impl<K: Eq + Hash + Clone, V: Empty + Default> KeyLocks<K, V> {
  89.     pub fn new() -> Self {
  90.         KeyLocks(Arc::default())
  91.     }
  92.  
  93.     fn key_ref(&self, key: K) -> KeyRef<K, V> {
  94.         KeyRef {
  95.             map: self.0.clone(),
  96.             key,
  97.         }
  98.     }
  99.  
  100.     pub async fn read(&self, key: K) -> OwnedReadGuard<K, V> {
  101.         OwnedReadGuard {
  102.             key: self.key_ref(key.clone()),
  103.             guard: ManuallyDrop::new(
  104.                 self.0
  105.                     .entry(key)
  106.                     .or_insert_with(Arc::default)
  107.                     .clone()
  108.                     .read_owned()
  109.                     .await,
  110.             ),
  111.         }
  112.     }
  113.  
  114.     pub async fn write(&self, key: K) -> OwnedWriteGuard<K, V> {
  115.         OwnedWriteGuard {
  116.             key: self.key_ref(key.clone()),
  117.             guard: ManuallyDrop::new(
  118.                 self.0
  119.                     .entry(key)
  120.                     .or_insert_with(Arc::default)
  121.                     .clone()
  122.                     .write_owned()
  123.                     .await,
  124.             ),
  125.         }
  126.     }
  127.  
  128.     pub fn len(&self) -> usize {
  129.         self.0.len()
  130.     }
  131. }
  132.  
  133. #[cfg(test)]
  134. mod test {
  135.     use super::KeyLocks;
  136.     use std::collections::BTreeSet;
  137.  
  138.     #[tokio::test]
  139.     async fn drop_only_if_empty() {
  140.         let locks = KeyLocks::<u32, BTreeSet<String>>::new();
  141.  
  142.         let mut lock = locks.write(1).await;
  143.         lock.insert("Hello".to_owned());
  144.         lock.insert("World".to_owned());
  145.         drop(lock);
  146.  
  147.         // Value is not empty and thus is not dropped
  148.         assert_eq!(locks.len(), 1);
  149.  
  150.         let mut lock = locks.write(1).await;
  151.         assert_eq!(lock.len(), 2);
  152.         lock.clear();
  153.         drop(lock);
  154.  
  155.         // Should be dropped now
  156.         assert_eq!(locks.len(), 0);
  157.     }
  158. }
  159.  
  160.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement