Skip to main content

dark_std/sync/
map_hash.rs

1use crate::lock::{SyncLock, SyncLockGuard};
2use serde::{Deserializer, Serialize, Serializer};
3use std::borrow::Borrow;
4use std::cell::UnsafeCell;
5use std::collections::{
6    hash_map::IntoIter as MapIntoIter, hash_map::Iter as MapIter, hash_map::IterMut as MapIterMut,
7    HashMap as Map,
8};
9use std::fmt::{Debug, Display, Formatter};
10use std::hash::Hash;
11use std::ops::{Deref, DerefMut};
12use std::sync::atomic::{AtomicBool, Ordering};
13use std::sync::Arc;
14
15use super::entry::{Entry, Retired};
16use super::snapshot::AtomicSnapshot;
17
18/// A concurrent HashMap with a Go `sync.Map`-style read/dirty architecture:
19///
20/// - `read`: an immutable snapshot, atomically published. `get` / `iter` /
21///   `Index` read it lock-free.
22/// - `dirty`: the canonical, mutable map, guarded by `lock`.
23///
24/// Every slot is an `Arc<Entry<V>>` shared between the snapshot and `dirty`.
25/// The entry holds an atomic pointer to the value, so updating an existing key
26/// swaps the pointer in place (O(1)) — no snapshot rebuild — and readers
27/// always see the latest value. New keys and removals are published lazily
28/// (tracked by the `amended` flag). Snapshots and retired values are kept
29/// alive until the map is dropped, so references returned by `get` stay valid.
30pub struct SyncHashMap<K: Eq + Hash, V> {
31    dirty: UnsafeCell<Map<K, Arc<Entry<V>>>>,
32    lock: SyncLock,
33    amended: AtomicBool,
34    read: AtomicSnapshot<Map<K, Arc<Entry<V>>>>,
35    retired: Retired<V>,
36}
37
38/// Safety: `dirty` is only ever accessed under `lock`; the `read` snapshot is
39/// immutable once published; values behind entries are immutable once
40/// published and swapped out atomically; retired values and retired snapshots
41/// are kept alive until the map is dropped, so references derived from `get`
42/// remain valid for the lifetime of `&self`.
43unsafe impl<K: Eq + Hash, V> Send for SyncHashMap<K, V> {}
44unsafe impl<K: Eq + Hash, V> Sync for SyncHashMap<K, V> {}
45
46impl<K, V> std::ops::Index<&K> for SyncHashMap<K, V>
47where
48    K: Eq + Hash + Clone,
49{
50    type Output = V;
51
52    fn index(&self, index: &K) -> &Self::Output {
53        self.get(index).expect("key not found")
54    }
55}
56
57impl<K, V> SyncHashMap<K, V>
58where
59    K: Eq + Hash,
60{
61    pub fn new_arc() -> Arc<Self> {
62        Arc::new(Self::new())
63    }
64
65    pub fn new() -> Self {
66        Self {
67            dirty: UnsafeCell::new(Map::new()),
68            lock: Default::default(),
69            amended: AtomicBool::new(false),
70            read: AtomicSnapshot::new(Map::new()),
71            retired: Retired::new(),
72        }
73    }
74
75    pub fn with_capacity(capacity: usize) -> Self {
76        Self {
77            dirty: UnsafeCell::new(Map::with_capacity(capacity)),
78            lock: Default::default(),
79            amended: AtomicBool::new(false),
80            read: AtomicSnapshot::new(Map::with_capacity(capacity)),
81            retired: Retired::new(),
82        }
83    }
84
85    pub fn with_map(map: Map<K, V>) -> Self {
86        let dirty = map
87            .into_iter()
88            .map(|(k, v)| (k, Arc::new(Entry::new(v))))
89            .collect();
90        Self {
91            read: AtomicSnapshot::new(Map::new()),
92            dirty: UnsafeCell::new(dirty),
93            lock: Default::default(),
94            amended: AtomicBool::new(true),
95            retired: Retired::new(),
96        }
97    }
98
99    /// Publish the current `dirty` map as a fresh immutable snapshot.
100    ///
101    /// The caller must hold `lock` (or have exclusive `&mut` access).
102    fn promote(&self)
103    where
104        K: Clone,
105    {
106        let dirty = unsafe { &*self.dirty.get() };
107        self.read.publish(dirty.clone());
108        // After publishing, `read` reflects `dirty`: nothing is pending.
109        self.amended.store(false, Ordering::Release);
110    }
111
112    /// Insert or replace the value for `k`, returning the previous value if
113    /// the key already existed.
114    ///
115    /// This requires `V: Clone` because the previous value must stay alive
116    /// for concurrent readers. Use [`set`](Self::set) when the value is not
117    /// `Clone` and the previous value is not needed.
118    pub fn insert(&self, k: K, v: V) -> Option<V>
119    where
120        K: Clone,
121        V: Clone,
122    {
123        let g = self.lock.lock();
124        let m = unsafe { &mut *self.dirty.get() };
125        if let Some(entry) = m.get(&k) {
126            // Update: swap the value in place (O(1)). The shared entry lets
127            // readers observe the new value without a snapshot rebuild.
128            let old = entry.swap(v);
129            let old_value = unsafe { (*old).clone() };
130            self.retired.push(old);
131            drop(g);
132            return Some(old_value);
133        }
134        // New key: leave it for lazy promotion and mark `amended`.
135        m.insert(k, Arc::new(Entry::new(v)));
136        self.amended.store(true, Ordering::Release);
137        drop(g);
138        None
139    }
140
141    pub fn insert_mut(&mut self, k: K, v: V) -> Option<V>
142    where
143        K: Clone,
144        V: Clone,
145    {
146        self.insert(k, v)
147    }
148
149    /// Insert or overwrite the value for `k` without returning the previous
150    /// one. Unlike [`insert`](Self::insert) this does **not** require
151    /// `V: Clone`, so it works with non-`Clone` values. Updating an existing
152    /// key swaps the value in place (O(1)); readers observe the new value
153    /// immediately.
154    pub fn set(&self, k: K, v: V) {
155        let g = self.lock.lock();
156        let m = unsafe { &mut *self.dirty.get() };
157        if let Some(entry) = m.get(&k) {
158            // Update: swap the value in place (O(1)). The shared entry lets
159            // readers observe the new value without a snapshot rebuild.
160            let old = entry.swap(v);
161            self.retired.push(old);
162        } else {
163            // New key: leave it for lazy promotion and mark `amended`.
164            m.insert(k, Arc::new(Entry::new(v)));
165            self.amended.store(true, Ordering::Release);
166        }
167        drop(g);
168    }
169
170    pub fn set_mut(&mut self, k: K, v: V) {
171        self.set(k, v)
172    }
173
174    /// Remove `k` and return its value.
175    ///
176    /// This requires `V: Clone` because the removed value must stay alive
177    /// for concurrent readers. Use [`delete`](Self::delete) when the value is
178    /// not `Clone` and the removed value is not needed.
179    pub fn remove(&self, k: &K) -> Option<V>
180    where
181        K: Clone,
182        V: Clone,
183    {
184        let g = self.lock.lock();
185        let m = unsafe { &mut *self.dirty.get() };
186        if let Some(entry) = m.remove(k) {
187            // Clone the value out; the entry (and its value) stays alive in the
188            // retired snapshot published below.
189            let v = entry.load().clone();
190            // Refresh the snapshot so `get` no longer serves the removed key.
191            self.promote();
192            drop(g);
193            return Some(v);
194        }
195        drop(g);
196        None
197    }
198
199    pub fn remove_mut(&mut self, k: &K) -> Option<V>
200    where
201        K: Clone,
202        V: Clone,
203    {
204        self.remove(k)
205    }
206
207    /// Remove `k` without returning its value. Unlike
208    /// [`remove`](Self::remove) this does **not** require `V: Clone`, so it
209    /// works with non-`Clone` values.
210    pub fn delete(&self, k: &K)
211    where
212        K: Clone,
213    {
214        let g = self.lock.lock();
215        let m = unsafe { &mut *self.dirty.get() };
216        if m.remove(k).is_some() {
217            // Refresh the snapshot so `get` no longer serves the removed key.
218            self.promote();
219        }
220        drop(g);
221    }
222
223    pub fn delete_mut(&mut self, k: &K)
224    where
225        K: Clone,
226    {
227        self.delete(k)
228    }
229
230    pub fn len(&self) -> usize {
231        if !self.amended.load(Ordering::Acquire) {
232            return self.read.load().len();
233        }
234        let g = self.lock.lock();
235        let r = unsafe { (&*self.dirty.get()).len() };
236        drop(g);
237        r
238    }
239
240    pub fn is_empty(&self) -> bool {
241        if !self.amended.load(Ordering::Acquire) {
242            return self.read.load().is_empty();
243        }
244        let g = self.lock.lock();
245        let r = unsafe { (&*self.dirty.get()).is_empty() };
246        drop(g);
247        r
248    }
249
250    pub fn clear(&self)
251    where
252        K: Clone,
253    {
254        let g = self.lock.lock();
255        unsafe { (&mut *self.dirty.get()).clear() };
256        self.promote();
257        drop(g);
258    }
259
260    pub fn clear_mut(&mut self)
261    where
262        K: Clone,
263    {
264        self.clear()
265    }
266
267    pub fn shrink_to_fit(&self) {
268        let g = self.lock.lock();
269        unsafe { (&mut *self.dirty.get()).shrink_to_fit() };
270        drop(g);
271    }
272
273    pub fn shrink_to_fit_mut(&mut self) {
274        unsafe { (&mut *self.dirty.get()).shrink_to_fit() }
275    }
276
277    pub fn from(map: Map<K, V>) -> Self
278    where
279        K: Eq + Hash,
280    {
281        let s = Self::with_map(map);
282        s
283    }
284
285    /// Returns a reference to the value corresponding to the key.
286    ///
287    /// The key may be any borrowed form of the map's key type, but
288    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
289    /// the key type.
290    ///
291    /// Reads are lock-free: the value is served from the immutable `read`
292    /// snapshot through a shared entry, so updates are visible immediately.
293    /// If the key was added to `dirty` since the last snapshot was published,
294    /// a fresh snapshot is published first.
295    ///
296    /// # Examples
297    ///
298    /// ```
299    /// use dark_std::sync::{SyncHashMap};
300    ///
301    /// let mut map = SyncHashMap::new();
302    /// map.insert_mut(1, "a");
303    /// assert_eq!(*map.get(&1).unwrap(), "a");
304    /// assert_eq!(map.get(&2).is_none(), true);
305    /// ```
306    #[inline]
307    pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
308    where
309        K: Borrow<Q> + Clone,
310        Q: Hash + Eq,
311    {
312        if let Some(entry) = self.read.load().get(k) {
313            return Some(entry.load());
314        }
315        // If nothing was written to `dirty` since the last snapshot was
316        // published, a snapshot miss is a real miss: no lock is needed.
317        if !self.amended.load(Ordering::Acquire) {
318            return None;
319        }
320        // Snapshot miss: the key may have been written to `dirty` without a
321        // snapshot refresh yet (lazy promotion). Publish a fresh snapshot and
322        // serve from it so the reference points into immutable, retained
323        // storage instead of the lock-guarded `dirty` map.
324        let g = self.lock.lock();
325        let found = unsafe { (&*self.dirty.get()).contains_key(k) };
326        if found {
327            self.promote();
328        }
329        drop(g);
330        if found {
331            self.read.load().get(k).map(|e| e.load())
332        } else {
333            None
334        }
335    }
336
337    /// Returns a mutable handle to the value for `k`, implemented with
338    /// copy-on-write: the value is cloned, the handle mutates the clone, and
339    /// the result is swapped back into the shared entry (O(1)) when the handle
340    /// is dropped. Concurrent readers may observe the pre-mutation value until
341    /// the handle is dropped.
342    #[inline]
343    pub fn get_mut(&self, k: &K) -> Option<HashMapRefMut<'_, K, V>>
344    where
345        K: Hash + Eq + Clone,
346        V: Clone,
347    {
348        let g = self.lock.lock();
349        let dirty = unsafe { &*self.dirty.get() };
350        let value = dirty.get(k)?.load().clone();
351        drop(g);
352        Some(HashMapRefMut {
353            k: k.clone(),
354            m: self,
355            value: Some(value),
356        })
357    }
358
359    #[inline]
360    pub fn contains_key(&self, x: &K) -> bool
361    where
362        K: PartialEq,
363    {
364        if self.read.load().contains_key(x) {
365            return true;
366        }
367        if !self.amended.load(Ordering::Acquire) {
368            return false;
369        }
370        let g = self.lock.lock();
371        let r = unsafe { (&*self.dirty.get()).contains_key(x) };
372        drop(g);
373        r
374    }
375
376    /// Iterate over the current contents. A fresh snapshot is published first,
377    /// so all entries written so far are visible.
378    pub fn iter(&self) -> Iter<'_, K, V>
379    where
380        K: Clone,
381    {
382        let g = self.lock.lock();
383        self.promote();
384        drop(g);
385        Iter {
386            inner: self.read.load().iter(),
387        }
388    }
389
390    pub fn iter_mut(&self) -> IterMut<'_, K, V>
391    where
392        K: Clone,
393        V: Clone,
394    {
395        let m = unsafe { &mut *self.dirty.get() };
396        IterMut {
397            m: self,
398            _g: self.lock.lock(),
399            inner: Some(m.iter_mut()),
400        }
401    }
402
403    pub fn into_iter(self) -> MapIntoIter<K, V> {
404        self.into_inner().into_iter()
405    }
406
407    pub fn into_inner(self) -> Map<K, V> {
408        // Move `dirty` out; the remaining fields (snapshots, retired values,
409        // lock) are dropped normally at the end of this function.
410        let dirty = self.dirty.into_inner();
411        dirty
412            .into_iter()
413            .map(|(k, entry)| (k, entry.take()))
414            .collect()
415    }
416}
417
418/// Iterator over `(&K, &V)`, served from the immutable snapshot.
419pub struct Iter<'a, K, V> {
420    inner: MapIter<'a, K, Arc<Entry<V>>>,
421}
422
423impl<'a, K, V> Iterator for Iter<'a, K, V> {
424    type Item = (&'a K, &'a V);
425
426    fn next(&mut self) -> Option<Self::Item> {
427        self.inner.next().map(|(k, e)| (k, e.load()))
428    }
429}
430
431impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
432    fn len(&self) -> usize {
433        self.inner.len()
434    }
435}
436
437/// Mutable iterator over `(&K, &mut V)`. Entries shared with snapshots are
438/// replaced with fresh unique ones; mutations are published when the iterator
439/// is dropped.
440pub struct IterMut<'a, K: Eq + Hash + Clone, V: Clone> {
441    m: &'a SyncHashMap<K, V>,
442    _g: SyncLockGuard<'a>,
443    inner: Option<MapIterMut<'a, K, Arc<Entry<V>>>>,
444}
445
446impl<'a, K: Eq + Hash + Clone, V: Clone> Drop for IterMut<'a, K, V> {
447    fn drop(&mut self) {
448        // Drop the `&mut` borrows into `dirty` first, then publish the
449        // mutations into a fresh snapshot. The lock (`_g`) is still held.
450        self.inner.take();
451        self.m.promote();
452    }
453}
454
455impl<'a, K: Eq + Hash + Clone, V: Clone> Iterator for IterMut<'a, K, V> {
456    type Item = (&'a K, &'a mut V);
457
458    fn next(&mut self) -> Option<Self::Item> {
459        let (k, entry) = self.inner.as_mut().unwrap().next()?;
460        // Make the entry uniquely owned so we can hand out `&mut V`.
461        if Arc::get_mut(entry).is_none() {
462            let current = entry.load().clone();
463            *entry = Arc::new(Entry::new(current));
464        }
465        Some((k, Arc::get_mut(entry).unwrap().get_mut()))
466    }
467}
468
469impl<'a, K: Eq + Hash + Clone, V: Clone> ExactSizeIterator for IterMut<'a, K, V> {
470    fn len(&self) -> usize {
471        self.inner.as_ref().unwrap().len()
472    }
473}
474
475pub struct HashMapRefMut<'a, K: Eq + Hash + Clone, V: Clone> {
476    k: K,
477    m: &'a SyncHashMap<K, V>,
478    value: Option<V>,
479}
480
481impl<'a, K: Eq + Hash + Clone, V: Clone> Drop for HashMapRefMut<'a, K, V> {
482    fn drop(&mut self) {
483        if let Some(v) = self.value.take() {
484            let g = self.m.lock.lock();
485            let dirty = unsafe { &mut *self.m.dirty.get() };
486            match dirty.get_mut(&self.k) {
487                Some(entry) => {
488                    let old = entry.swap(v);
489                    self.m.retired.push(old);
490                }
491                // The key was removed while the handle was held: keep the
492                // mutation by re-inserting it.
493                None => {
494                    dirty.insert(self.k.clone(), Arc::new(Entry::new(v)));
495                    self.m.amended.store(true, Ordering::Release);
496                }
497            }
498            drop(g);
499        }
500    }
501}
502
503impl<'a, K: Eq + Hash + Clone, V: Clone> Deref for HashMapRefMut<'_, K, V> {
504    type Target = V;
505
506    fn deref(&self) -> &Self::Target {
507        self.value.as_ref().unwrap()
508    }
509}
510
511impl<'a, K: Eq + Hash + Clone, V: Clone> DerefMut for HashMapRefMut<'_, K, V> {
512    fn deref_mut(&mut self) -> &mut Self::Target {
513        self.value.as_mut().unwrap()
514    }
515}
516
517impl<'a, K: Eq + Hash + Clone, V: Clone> Debug for HashMapRefMut<'_, K, V>
518where
519    V: Debug,
520{
521    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
522        self.value.as_ref().unwrap().fmt(f)
523    }
524}
525
526impl<'a, K: Eq + Hash + Clone, V: Clone> Display for HashMapRefMut<'_, K, V>
527where
528    V: Display,
529{
530    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
531        self.value.as_ref().unwrap().fmt(f)
532    }
533}
534
535impl<'a, K: Eq + Hash + Clone, V: Clone> PartialEq<Self> for HashMapRefMut<'_, K, V>
536where
537    V: Eq,
538{
539    fn eq(&self, other: &Self) -> bool {
540        self.value
541            .as_ref()
542            .unwrap()
543            .eq(&other.value.as_ref().unwrap())
544    }
545}
546
547impl<'a, K: Eq + Hash + Clone, V: Clone> Eq for HashMapRefMut<'_, K, V> where V: Eq {}
548
549impl<'a, K: Clone, V> IntoIterator for &'a SyncHashMap<K, V>
550where
551    K: Eq + Hash,
552{
553    type Item = (&'a K, &'a V);
554    type IntoIter = Iter<'a, K, V>;
555
556    fn into_iter(self) -> Self::IntoIter {
557        self.iter()
558    }
559}
560
561impl<K, V> IntoIterator for SyncHashMap<K, V>
562where
563    K: Eq + Hash,
564{
565    type Item = (K, V);
566    type IntoIter = MapIntoIter<K, V>;
567
568    fn into_iter(self) -> Self::IntoIter {
569        self.into_iter()
570    }
571}
572
573impl<K: Eq + Hash, V> From<Map<K, V>> for SyncHashMap<K, V> {
574    fn from(arg: Map<K, V>) -> Self {
575        Self::from(arg)
576    }
577}
578
579impl<K, V> serde::Serialize for SyncHashMap<K, V>
580where
581    K: Eq + Hash + Serialize,
582    V: Serialize,
583{
584    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
585    where
586        S: Serializer,
587    {
588        use serde::ser::SerializeMap;
589        let g = self.lock.lock();
590        let dirty = unsafe { &*self.dirty.get() };
591        let mut m = serializer.serialize_map(Some(dirty.len()))?;
592        for (k, e) in dirty.iter() {
593            m.serialize_entry(k, e.load())?;
594        }
595        drop(g);
596        m.end()
597    }
598}
599
600impl<'de, K, V> serde::Deserialize<'de> for SyncHashMap<K, V>
601where
602    K: Eq + Hash + serde::Deserialize<'de>,
603    V: serde::Deserialize<'de>,
604{
605    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
606    where
607        D: Deserializer<'de>,
608    {
609        let m = Map::deserialize(deserializer)?;
610        Ok(Self::from(m))
611    }
612}
613
614impl<K, V> Debug for SyncHashMap<K, V>
615where
616    K: Eq + Hash + Debug,
617    V: Debug,
618{
619    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
620        let g = self.lock.lock();
621        let r = unsafe { (&*self.dirty.get()).fmt(f) };
622        drop(g);
623        r
624    }
625}
626
627impl<K, V> Display for SyncHashMap<K, V>
628where
629    K: Eq + Hash + Display,
630    V: Display,
631{
632    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
633        use std::fmt::Pointer;
634        let g = self.lock.lock();
635        let r = unsafe { (&*self.dirty.get()).fmt(f) };
636        drop(g);
637        r
638    }
639}
640
641impl<K: Clone + Eq + Hash, V: Clone> Clone for SyncHashMap<K, V> {
642    fn clone(&self) -> Self {
643        let g = self.lock.lock();
644        let dirty = unsafe { &*self.dirty.get() };
645        let m = dirty
646            .iter()
647            .map(|(k, e)| (k.clone(), e.load().clone()))
648            .collect();
649        drop(g);
650        SyncHashMap::from(m)
651    }
652}
653
654impl<K: Eq + Hash, V> Default for SyncHashMap<K, V> {
655    fn default() -> Self {
656        SyncHashMap::new()
657    }
658}