Skip to main content

dark_std/sync/
vec.rs

1use parking_lot::Mutex;
2use serde::{Deserializer, Serialize, Serializer};
3use std::cell::UnsafeCell;
4use std::fmt::{Debug, Display, Formatter};
5use std::slice::{Iter as SliceIter, IterMut as SliceIterMut};
6use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
7use std::sync::Arc;
8use std::vec::IntoIter;
9
10use super::{ReadGuard, ReadMapGuard, WriteGuard, WriteLock};
11
12/// Read guard returned by [`SyncVec::get`].
13pub type VecGet<'a, V> = ReadGuard<'a, V>;
14
15/// Write guard returned by [`SyncVec::get_mut`].
16pub type VecRefMut<'a, V> = WriteGuard<'a, V>;
17
18/// Read iterator returned by [`SyncVec::iter`].
19///
20/// The iterator is `Send` (when `V: Sync`) and may be moved between threads:
21/// the reader counter is a shared atomic owned by the container, so releasing
22/// it from another thread (on drop) is safe.
23pub struct VecIter<'a, V> {
24    count: &'a AtomicUsize,
25    inner: SliceIter<'a, V>,
26}
27
28impl<'a, V> Drop for VecIter<'a, V> {
29    fn drop(&mut self) {
30        self.count.fetch_sub(1, Ordering::Release);
31    }
32}
33
34impl<'a, V> Iterator for VecIter<'a, V> {
35    type Item = &'a V;
36
37    fn next(&mut self) -> Option<Self::Item> {
38        self.inner.next()
39    }
40}
41
42/// Write iterator returned by [`SyncVec::iter_mut`].
43pub struct VecIterMut<'a, V> {
44    _w: WriteLock<'a>,
45    inner: SliceIterMut<'a, V>,
46}
47
48impl<'a, V> Iterator for VecIterMut<'a, V> {
49    type Item = &'a mut V;
50
51    fn next(&mut self) -> Option<Self::Item> {
52        self.inner.next()
53    }
54}
55
56/// An asynchronous vector that can be safely shared between threads.
57///
58/// Reads are lock-free: `get`/`iter`/`dirty_ref`/`len`/`contains` only
59/// register a reader slot with an atomic counter and then read the vector
60/// without any lock (readers never block each other and never touch a lock
61/// word). Writes take a mutex, raise a `writing` flag and wait until all
62/// in-flight readers are gone before mutating the vector in place (amortised
63/// O(1) push, no whole-container copy).
64///
65/// # Deadlock note
66/// A read guard makes writers wait until it is dropped. Do not call a write
67/// method while a read/write guard is alive in the same scope: drop the guard
68/// first (e.g. `drop(g)` before `push`/`remove`/`get_mut`), otherwise the
69/// writer waits for its own guard and deadlocks.
70pub struct SyncVec<V> {
71    dirty: UnsafeCell<Vec<V>>,
72    write: Mutex<()>,
73    id: usize,
74    writing: AtomicBool,
75    registry: Mutex<Vec<std::boxed::Box<AtomicUsize>>>,
76}
77
78// SAFETY: all writers hold `write` and wait for `readers` to drain before
79// touching `dirty`; readers either see a consistent snapshot or retry while a
80// writer is active, so concurrent access to `dirty` is race-free.
81unsafe impl<V: Send> Send for SyncVec<V> {}
82unsafe impl<V: Sync> Sync for SyncVec<V> {}
83
84impl<V> SyncVec<V> {
85    #[inline]
86    fn begin_read(&self) -> &AtomicUsize {
87        // The counter lives in thread-local storage: concurrent readers only
88        // touch their own cache line and never contend with each other. SeqCst
89        // closes the store-buffering window with the writer's all-zero scan.
90        let count = super::reader_count_for(self.id, &self.registry);
91        loop {
92            count.fetch_add(1, Ordering::SeqCst);
93            if !self.writing.load(Ordering::SeqCst) {
94                return count;
95            }
96            count.fetch_sub(1, Ordering::SeqCst);
97            std::thread::yield_now();
98        }
99    }
100
101    #[inline]
102    fn begin_write(&self) -> WriteLock<'_> {
103        let lock = self.write.lock();
104        self.writing.store(true, Ordering::SeqCst);
105        loop {
106            let registry = self.registry.lock();
107            let all_zero = registry.iter().all(|c| c.load(Ordering::SeqCst) == 0);
108            if all_zero {
109                break;
110            }
111            drop(registry);
112            std::thread::yield_now();
113        }
114        WriteLock::new(lock, &self.writing)
115    }
116
117    pub fn new_arc() -> Arc<Self> {
118        Arc::new(Self::new())
119    }
120
121    pub fn new() -> Self {
122        Self {
123            dirty: UnsafeCell::new(Vec::new()),
124            write: Mutex::new(()),
125            id: super::CONTAINER_ID.fetch_add(1, Ordering::Relaxed),
126            writing: AtomicBool::new(false),
127            registry: Mutex::new(Vec::new()),
128        }
129    }
130
131    pub fn with_capacity(capacity: usize) -> Self {
132        Self {
133            dirty: UnsafeCell::new(Vec::with_capacity(capacity)),
134            write: Mutex::new(()),
135            id: super::CONTAINER_ID.fetch_add(1, Ordering::Relaxed),
136            writing: AtomicBool::new(false),
137            registry: Mutex::new(Vec::new()),
138        }
139    }
140
141    pub fn with_vec(vec: Vec<V>) -> Self {
142        Self {
143            dirty: UnsafeCell::new(vec),
144            write: Mutex::new(()),
145            id: super::CONTAINER_ID.fetch_add(1, Ordering::Relaxed),
146            writing: AtomicBool::new(false),
147            registry: Mutex::new(Vec::new()),
148        }
149    }
150
151    pub fn insert(&self, index: usize, v: V) -> Option<V> {
152        let _w = self.begin_write();
153        unsafe { &mut *self.dirty.get() }.insert(index, v);
154        None
155    }
156
157    pub fn set(&self, index: usize, v: V) -> Option<V> {
158        let _w = self.begin_write();
159        let m = unsafe { &mut *self.dirty.get() };
160        m[index] = v;
161        None
162    }
163
164    pub fn push(&self, v: V) -> Option<V> {
165        let _w = self.begin_write();
166        unsafe { &mut *self.dirty.get() }.push(v);
167        None
168    }
169
170    pub fn pushes(&self, arr: Vec<V>) -> Option<V> {
171        let _w = self.begin_write();
172        unsafe { &mut *self.dirty.get() }.extend(arr);
173        None
174    }
175
176    pub fn push_mut(&mut self, v: V) -> Option<V> {
177        unsafe { &mut *self.dirty.get() }.push(v);
178        None
179    }
180
181    pub fn pop(&self) -> Option<V> {
182        let _w = self.begin_write();
183        unsafe { &mut *self.dirty.get() }.pop()
184    }
185
186    pub fn pop_mut(&mut self) -> Option<V> {
187        unsafe { &mut *self.dirty.get() }.pop()
188    }
189
190    pub fn remove(&self, index: usize) -> Option<V> {
191        let _w = self.begin_write();
192        let m = unsafe { &mut *self.dirty.get() };
193        if m.len() > index {
194            Some(m.remove(index))
195        } else {
196            None
197        }
198    }
199
200    pub fn remove_mut(&mut self, index: usize) -> Option<V> {
201        let m = unsafe { &mut *self.dirty.get() };
202        if m.len() > index {
203            Some(m.remove(index))
204        } else {
205            None
206        }
207    }
208
209    pub fn len(&self) -> usize {
210        let count = self.begin_read();
211        let n = unsafe { &*self.dirty.get() }.len();
212        count.fetch_sub(1, Ordering::Release);
213        n
214    }
215
216    pub fn is_empty(&self) -> bool {
217        let count = self.begin_read();
218        let b = unsafe { &*self.dirty.get() }.is_empty();
219        count.fetch_sub(1, Ordering::Release);
220        b
221    }
222
223    pub fn clear(&self) {
224        let _w = self.begin_write();
225        unsafe { &mut *self.dirty.get() }.clear();
226    }
227
228    pub fn shrink_to_fit(&self) {
229        let _w = self.begin_write();
230        unsafe { &mut *self.dirty.get() }.shrink_to_fit();
231    }
232
233    pub fn from(vec: Vec<V>) -> Self {
234        Self::with_vec(vec)
235    }
236
237    /// Returns a read-guarded reference to the value at `index`.
238    ///
239    /// The read is lock-free: it only registers a reader slot, so concurrent
240    /// reads never block each other and never take a lock. Writers wait for
241    /// the returned guard to be dropped before mutating the vector.
242    #[inline]
243    pub fn get(&self, index: usize) -> Option<VecGet<'_, V>> {
244        let count = self.begin_read();
245        let m = unsafe { &*self.dirty.get() };
246        match m.get(index) {
247            Some(v) => Some(ReadGuard::new(count, v)),
248            None => {
249                count.fetch_sub(1, Ordering::Release);
250                None
251            }
252        }
253    }
254
255    /// Returns a write-guarded mutable reference to the value at `index`.
256    ///
257    /// The guard holds the writer lock (writers are mutually exclusive and
258    /// wait for in-flight readers) until it is dropped, so the mutable
259    /// reference can never race with concurrent readers or writers. Drop it
260    /// before calling another method from the same scope.
261    #[inline]
262    pub fn get_mut(&self, index: usize) -> Option<VecRefMut<'_, V>> {
263        let w = self.begin_write();
264        let m = unsafe { &mut *self.dirty.get() };
265        match m.get_mut(index) {
266            Some(v) => Some(WriteGuard::new(w, v)),
267            None => None,
268        }
269    }
270
271    #[inline]
272    pub fn contains(&self, x: &V) -> bool
273    where
274        V: PartialEq,
275    {
276        let count = self.begin_read();
277        let b = unsafe { &*self.dirty.get() }.contains(x);
278        count.fetch_sub(1, Ordering::Release);
279        b
280    }
281
282    pub fn iter(&self) -> VecIter<'_, V> {
283        let count = self.begin_read();
284        let m = unsafe { &*self.dirty.get() };
285        VecIter {
286            count,
287            inner: m.iter(),
288        }
289    }
290
291    pub fn iter_mut(&self) -> VecIterMut<'_, V> {
292        let w = self.begin_write();
293        let m = unsafe { &mut *self.dirty.get() };
294        VecIterMut {
295            _w: w,
296            inner: m.iter_mut(),
297        }
298    }
299
300    pub fn into_iter(self) -> IntoIter<V> {
301        self.into_inner().into_iter()
302    }
303
304    pub fn dirty_ref(&self) -> ReadMapGuard<'_, Vec<V>> {
305        let count = self.begin_read();
306        let m = unsafe { &*self.dirty.get() };
307        ReadMapGuard::new(count, m)
308    }
309
310    pub fn into_inner(self) -> Vec<V> {
311        self.dirty.into_inner()
312    }
313}
314
315impl<V> IntoIterator for SyncVec<V> {
316    type Item = V;
317    type IntoIter = IntoIter<V>;
318
319    fn into_iter(self) -> Self::IntoIter {
320        self.into_iter()
321    }
322}
323
324impl<V> Serialize for SyncVec<V>
325where
326    V: Serialize,
327{
328    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
329    where
330        S: Serializer,
331    {
332        self.dirty_ref().serialize(serializer)
333    }
334}
335
336impl<'de, V> serde::Deserialize<'de> for SyncVec<V>
337where
338    V: serde::Deserialize<'de>,
339{
340    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
341    where
342        D: Deserializer<'de>,
343    {
344        let m = Vec::deserialize(deserializer)?;
345        Ok(Self::from(m))
346    }
347}
348
349impl<V> Debug for SyncVec<V>
350where
351    V: Debug,
352{
353    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
354        Debug::fmt(&*self.dirty_ref(), f)
355    }
356}
357
358impl<V> Display for SyncVec<V>
359where
360    V: Debug,
361{
362    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
363        Debug::fmt(&*self.dirty_ref(), f)
364    }
365}
366
367impl<V: PartialEq> PartialEq for SyncVec<V> {
368    fn eq(&self, other: &Self) -> bool {
369        (*self.dirty_ref()).eq(&*other.dirty_ref())
370    }
371}
372
373impl<V: Clone> Clone for SyncVec<V> {
374    fn clone(&self) -> Self {
375        SyncVec::from(self.dirty_ref().to_vec())
376    }
377}
378
379impl<V> Default for SyncVec<V> {
380    fn default() -> Self {
381        SyncVec::new()
382    }
383}
384
385#[macro_export]
386macro_rules! sync_vec {
387    () => (
388        $crate::sync::SyncVec::new()
389    );
390    ($elem:expr; $n:expr) => (
391        $crate::sync::SyncVec::with_vec(vec![$elem;$n])
392    );
393    ($($x:expr),+ $(,)?) => (
394        $crate::sync::SyncVec::with_vec(vec![$($x),+,])
395    );
396}