Skip to main content

dark_std/sync/
map_btree.rs

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