persistent_stack/
lib.rs

1use std::sync::Arc;
2
3struct PersistentStackNode<T> {
4    data: T,
5    parent: Option<Arc<PersistentStackNode<T>>>,
6}
7
8/// # Concurrent persistent stack
9/// Supportted operations:
10/// - clone *O*(1)
11/// - push *O*(1)
12/// - pop *O*(1)
13/// - iterate *O*(n)
14///
15/// ```rust
16/// use persistent_stack::PersistentStack;
17///
18/// let mut s1 = PersistentStack::new();
19/// s1.push(1);
20/// let mut s2 = s1.clone();
21/// std::thread::spawn(move || {
22///     s2.push(2);
23///     assert_eq!(s2.iter().copied().collect::<Vec<_>>(), vec![2, 1]);
24///     std::thread::sleep(std::time::Duration::from_millis(20));
25///     s2.push(4);
26///     assert_eq!(s2.iter().copied().collect::<Vec<_>>(), vec![4, 2, 1]);
27/// });
28/// s1.push(3);
29/// assert_eq!(s1.iter().copied().collect::<Vec<_>>(), vec![3, 1]);
30/// std::thread::sleep(std::time::Duration::from_millis(20));
31/// s1.push(5);
32/// assert_eq!(s1.iter().copied().collect::<Vec<_>>(), vec![5, 3, 1]);
33/// ```
34pub struct PersistentStack<T>(Option<Arc<PersistentStackNode<T>>>);
35
36impl<T> Default for PersistentStack<T> {
37    fn default() -> PersistentStack<T> {
38        PersistentStack(None)
39    }
40}
41
42impl<T> Clone for PersistentStack<T> {
43    fn clone(&self) -> Self {
44        PersistentStack(self.0.as_ref().map(|x| Arc::clone(x)))
45    }
46}
47
48#[derive(Debug, Clone, Copy, Eq, PartialEq)]
49pub enum PersistentStackPopError {
50    CantUnwrap,
51    RootIsReached,
52}
53
54impl<T> PersistentStack<T> {
55    /// Creates new empty persistent stack
56    ///
57    /// ```rust
58    /// use persistent_stack::PersistentStack;
59    ///
60    /// let s = PersistentStack::<i32>::new();
61    /// assert!(s.into_iter().next().is_none())
62    /// ```
63    pub fn new() -> PersistentStack<T> {
64        Self::default()
65    }
66
67    /// Pushes `data` to end of `self` (affects only current copy of stack)
68    ///
69    /// ```rust
70    /// use persistent_stack::PersistentStack;
71    /// use std::sync::Arc;
72    ///
73    /// let mut s1 = PersistentStack::new();
74    /// s1.push(1);
75    /// let mut s2 = s1.clone();
76    /// s2.push(2);
77    /// assert_eq!(s1.into_iter().collect::<Vec<_>>(), [&1]);
78    /// assert_eq!(s2.into_iter().collect::<Vec<_>>(), [&2, &1]);
79    pub fn push(&mut self, data: T) {
80        let node = PersistentStackNode {
81            data,
82            parent: self.0.as_ref().map(|x| Arc::clone(x)),
83        };
84        *self = PersistentStack(Some(Arc::new(node)));
85    }
86
87    /// Pops value from stack and tries to return it
88    ///
89    /// Returns `Ok(data)` if only this copy of stack owned `data`
90    ///
91    /// Returns `Err(CantUnwrap)` if there are other copies, which own `data`
92    ///
93    /// Returns `Err(RootIsReached)` if nothing to pop
94    ///
95    /// ```rust
96    /// use persistent_stack::{PersistentStack, PersistentStackPopError::*};
97    ///
98    /// let mut s1 = PersistentStack::new();
99    /// s1.push(1);
100    /// s1.push(2);
101    /// let mut s2 = s1.clone();
102    /// s1.push(3);
103    /// s2.push(4);
104    /// assert_eq!(s2.pop(), Ok(4)); // only s2 owned 4
105    /// assert_eq!(s2.pop(), Err(CantUnwrap)); // s1 also owns 2
106    /// let mut s3 = s2.clone();
107    /// assert_eq!(s2.pop(), Err(CantUnwrap)); // s1 also owns 1
108    /// assert_eq!(s2.pop(), Err(RootIsReached)); // There are no elements in s2
109    /// s3.push(5);
110    /// assert_eq!(s3.iter().copied().collect::<Vec<_>>(), vec![5, 1]); // s3 is cloned, when s2 was [1]
111    pub fn pop(&mut self) -> Result<T, PersistentStackPopError> {
112        let s = self.0.take();
113        s.map(|node| {
114            self.0 = node.parent.as_ref().cloned();
115            Arc::try_unwrap(node)
116                .map(|node| node.data)
117                .map_err(|_| PersistentStackPopError::CantUnwrap)
118        })
119        .unwrap_or(Err(PersistentStackPopError::RootIsReached))
120    }
121
122    /// Creates iterator over `self` by reference
123    ///
124    /// ```rust
125    /// use persistent_stack::PersistentStack;
126    ///
127    /// let mut s = PersistentStack::new();
128    /// s.push(1);
129    /// s.push(2);
130    /// s.push(3);
131    /// assert_eq!(s.iter().collect::<Vec<_>>(), [&3, &2, &1]);
132    /// s.push(4); // s didn't move out
133    pub fn iter(&self) -> PersistentStackIter<T> {
134        PersistentStackIter(self.0.as_deref())
135    }
136}
137
138/// Iterator over persistent stack
139pub struct PersistentStackIter<'a, T>(Option<&'a PersistentStackNode<T>>);
140
141impl<'a, T> IntoIterator for &'a PersistentStack<T> {
142    type IntoIter = PersistentStackIter<'a, T>;
143    type Item = &'a T;
144
145    fn into_iter(self) -> Self::IntoIter {
146        PersistentStackIter(self.0.as_deref())
147    }
148}
149
150impl<'a, T> Iterator for PersistentStackIter<'a, T> {
151    type Item = &'a T;
152
153    fn next(&mut self) -> Option<Self::Item> {
154        self.0.map(|node| {
155            self.0 = node.parent.as_deref();
156            &node.data
157        })
158    }
159}
160
161mod tests {
162    #[test]
163    fn test_persistent_stack() {
164        let mut s1 = crate::PersistentStack::new();
165        s1.push(1);
166        s1.push(2);
167        let mut s2 = s1.clone();
168        s1.push(3);
169        s2.push(4);
170        assert_eq!(s1.into_iter().map(|x| *x).collect::<Vec<_>>(), [3, 2, 1]);
171        assert_eq!(s2.into_iter().map(|x| *x).collect::<Vec<_>>(), [4, 2, 1]);
172    }
173
174    #[test]
175    fn readme_example() {
176        use crate::PersistentStack;
177
178        let mut s1 = PersistentStack::new();
179        s1.push(1);
180
181        let mut s2 = s1.clone(); // O(1) operation
182
183        std::thread::spawn(move || {
184            s2.push(2); // PersistentStack values can be shared safely
185            assert_eq!(s2.iter().copied().collect::<Vec<_>>(), vec![2, 1]);
186
187            std::thread::sleep(std::time::Duration::from_millis(20));
188
189            s2.push(4);
190            assert_eq!(s2.iter().copied().collect::<Vec<_>>(), vec![4, 2, 1]);
191
192            assert_eq!(s2.pop(), Ok(4)); // We can also pop values from stack
193        });
194
195        s1.push(3);
196        assert_eq!(s1.iter().copied().collect::<Vec<_>>(), vec![3, 1]);
197
198        std::thread::sleep(std::time::Duration::from_millis(20));
199
200        s1.push(5);
201        assert_eq!(s1.iter().copied().collect::<Vec<_>>(), vec![5, 3, 1]);
202    }
203}