Skip to main content

dark_std/sync/
vec.rs

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