Skip to main content

low_latency_data_structures/seqlock/
writer.rs

1use std::marker::PhantomData;
2use std::sync::Arc;
3
4use crate::seqlock::lock::SeqLock;
5
6/// The writing handle of a [`SeqLock`](crate::seqlock).
7///
8/// `Writer` is [`Send`] but not [`Sync`]: at most one thread may write at a
9/// time. To enforce that, the type is neither [`Clone`] nor [`Copy`].
10pub struct Writer<T>
11where
12    T: bytemuck::AnyBitPattern,
13{
14    inner: Arc<SeqLock<T>>,
15    // Remove possibility to share ownership
16    _not_sync: PhantomData<*const ()>,
17}
18
19impl<T> std::fmt::Debug for Writer<T>
20where
21    T: bytemuck::AnyBitPattern,
22{
23    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24        f.debug_struct("Writer").finish_non_exhaustive()
25    }
26}
27
28// SAFETY: SeqLock<T> is Send, we just need to forbid Sync.
29unsafe impl<T> Send for Writer<T> where T: bytemuck::AnyBitPattern {}
30
31impl<T> Writer<T>
32where
33    T: bytemuck::AnyBitPattern,
34{
35    pub(super) fn new(seqlock: Arc<SeqLock<T>>) -> Self {
36        Self {
37            inner: seqlock,
38            _not_sync: PhantomData,
39        }
40    }
41
42    /// Writes a new value, replacing the current one.
43    ///
44    /// Wait-free. Concurrent readers may observe the in-progress write but
45    /// will retry until they see a consistent value.
46    ///
47    /// # Examples
48    ///
49    /// ```
50    /// use low_latency_data_structures::seqlock::new;
51    ///
52    /// let (writer, reader) = new(0u64);
53    /// writer.write(7);
54    /// assert_eq!(reader.read(), 7);
55    /// ```
56    #[inline]
57    pub fn write(&self, value: T) {
58        self.inner.write(value)
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65
66    // Writer can be sent to another thread.
67    static_assertions::assert_impl_all!(Writer<u32>: Send);
68    // Though, there may only be single writer at most.
69    static_assertions::assert_not_impl_any!(Writer<u32>: Sync, Clone, Copy);
70    static_assertions::assert_not_impl_any!(Arc<Writer<u32>>: Send, Sync, Copy);
71}