qrwcell/
lib.rs

1//! # qrwcell - quick read-write cell
2//!
3//! Read-write cell that aims to reduce the amount of blocking compared to a
4//! single read-write lock.
5//!
6//! The cell has two slots - one for reading and one for writing. Writing
7//! alternates the slot that is currently served to readers, thereby minimising
8//! blocking on a reader-writer lock.
9
10mod raw;
11
12use std::sync::Arc;
13use std::sync::Weak;
14
15use self::raw::RawQrwCell;
16
17/// A quick read-write cell.
18pub struct QrwCell<T> {
19    raw: RawQrwCell<T>,
20}
21
22impl<T> QrwCell<T> {
23    /// Create a new cell.
24    #[inline(always)]
25    pub const fn new() -> Self {
26        Self {
27            raw: RawQrwCell::new(),
28        }
29    }
30
31    /// Create a new cell with a value.
32    #[inline(always)]
33    pub fn with_value(value: T) -> Self {
34        Self {
35            raw: RawQrwCell::with_value(value),
36        }
37    }
38
39    /// Get the current value of the cell.
40    ///
41    /// This function will panic if the cell is in an uninitialized state.
42    #[inline(always)]
43    #[must_use]
44    pub fn get(&self) -> Arc<T> {
45        self.raw.get()
46    }
47
48    /// Get the current value of the cell (as a weak pointer).
49    ///
50    /// This function will panic if the cell is in an uninitialized state.
51    #[inline(always)]
52    pub fn get_weak(&self) -> Weak<T> {
53        self.raw.get_weak()
54    }
55
56    /// Update the cell, returning the old value.
57    ///
58    /// If the cell did not previously have a value, the same value is returned.
59    #[inline(always)]
60    pub fn update(&self, value: T) -> Arc<T> {
61        self.raw.update(value)
62    }
63}
64
65impl<T: Default> Default for QrwCell<T> {
66    fn default() -> Self {
67        Self {
68            raw: RawQrwCell::default(),
69        }
70    }
71}
72
73impl<T: Default> QrwCell<T> {
74    /// Update the cell with the default value for this type,
75    /// returning the old value.
76    #[inline(always)]
77    pub fn update_with_default(&self) -> Arc<T> {
78        self.update(T::default())
79    }
80}
81
82#[cfg(test)]
83mod test {
84    use crate::QrwCell;
85
86    #[test]
87    #[should_panic]
88    fn test_new_get_panic() {
89        let cell: QrwCell<Vec<u32>> = QrwCell::new();
90        let _ = cell.get();
91    }
92
93    #[test]
94    #[should_panic]
95    fn test_new_get_weak_panic() {
96        let cell: QrwCell<Vec<u32>> = QrwCell::new();
97        let _ = cell.get_weak();
98    }
99
100    #[test]
101    fn test_default_get() {
102        let cell: QrwCell<Vec<u32>> = QrwCell::default();
103        assert_eq!(<Vec<u32>>::default(), *cell.get())
104    }
105
106    #[test]
107    fn test_default_get_weak() {
108        let cell: QrwCell<Vec<u32>> = QrwCell::default();
109        assert_eq!(
110            <Vec<u32>>::default(),
111            *cell
112                .get_weak()
113                .upgrade()
114                .expect("Weak pointer missing value")
115        )
116    }
117
118    #[test]
119    fn test_with_value_get() {
120        let cell = QrwCell::with_value(vec![42, 42, 42, 42]);
121        assert_eq!(vec![42, 42, 42, 42], *cell.get())
122    }
123
124    #[test]
125    fn test_with_value_get_weak() {
126        let cell: QrwCell<Vec<u32>> = QrwCell::with_value(vec![42, 42, 42, 42]);
127        assert_eq!(
128            vec![42, 42, 42, 42],
129            *cell
130                .get_weak()
131                .upgrade()
132                .expect("Weak pointer missing value")
133        )
134    }
135
136    #[test]
137    fn test_update() {
138        let cell = QrwCell::new();
139
140        let vec = vec![0, 0, 0, 0];
141        let vec_clone = vec.clone();
142        assert_eq!(*cell.update(vec), vec_clone);
143
144        let new_vec = vec![42, 0, 0, 0];
145        let new_vec_clone = new_vec.clone();
146        assert_eq!(*cell.update(new_vec), vec_clone);
147        assert_eq!(*cell.get(), new_vec_clone);
148    }
149
150    #[test]
151    fn test_update_default() {
152        let cell = QrwCell::new();
153
154        assert_eq!(*cell.update(vec![0, 0, 0, 0]), vec![0, 0, 0, 0]);
155
156        assert_eq!(*cell.update_with_default(), vec![0, 0, 0, 0]);
157        assert_eq!(*cell.get(), Vec::default());
158    }
159
160    #[test]
161    fn test_get_weak_update() {
162        let cell = QrwCell::with_value(vec![42, 42, 42, 42]);
163        assert_eq!(*cell.get_weak().upgrade().unwrap(), vec![42, 42, 42, 42]);
164
165        let weak = cell.get_weak();
166        cell.update_with_default();
167        assert_eq!(weak.upgrade(), None);
168    }
169}