Skip to main content

sdd/
stack.rs

1//! [`Stack`] is a lock-free concurrent last-in-first-out container.
2
3use std::fmt::{self, Debug};
4use std::iter::FusedIterator;
5use std::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed};
6
7use super::linked_list::{LinkedEntry, LinkedList};
8use super::{AtomicShared, Guard, Ptr, Shared, Tag};
9
10/// [`Stack`] is a lock-free concurrent last-in-first-out container.
11pub struct Stack<T> {
12    /// `newest` points to the newest entry in the [`Stack`].
13    newest: AtomicShared<LinkedEntry<T>>,
14}
15
16/// An iterator over the entries of a [`Stack`].
17///
18/// [`Iter`] reads the newest entry first.
19pub struct Iter<'g, T> {
20    current: Ptr<'g, LinkedEntry<T>>,
21    guard: &'g Guard,
22}
23
24impl<T: 'static> Stack<T> {
25    /// Pushes an instance of `T`.
26    ///
27    /// Returns a [`Shared`] holding a strong reference to the newly pushed entry.
28    ///
29    /// # Examples
30    ///
31    /// ```
32    /// use sdd::Stack;
33    ///
34    /// let stack: Stack<usize> = Stack::default();
35    ///
36    /// assert_eq!(**stack.push(11), 11);
37    /// ```
38    #[inline]
39    pub fn push(&self, val: T) -> Shared<LinkedEntry<T>> {
40        match self.push_if_internal(val, |_| true, &Guard::new()) {
41            Ok(entry) => entry,
42            Err(_) => {
43                unreachable!();
44            }
45        }
46    }
47
48    /// Pushes an instance of `T` if the newest entry satisfies the given condition.
49    ///
50    /// # Errors
51    ///
52    /// Returns an error containing the supplied instance if the condition is not met.
53    ///
54    /// # Examples
55    ///
56    /// ```
57    /// use sdd::Stack;
58    ///
59    /// let stack: Stack<usize> = Stack::default();
60    ///
61    /// stack.push(11);
62    ///
63    /// assert!(stack.push_if(17, |e| e.map_or(false, |x| **x == 11)).is_ok());
64    /// assert!(stack.push_if(29, |e| e.map_or(false, |x| **x == 11)).is_err());
65    /// ```
66    #[inline]
67    pub fn push_if<F: FnMut(Option<&LinkedEntry<T>>) -> bool>(
68        &self,
69        val: T,
70        cond: F,
71    ) -> Result<Shared<LinkedEntry<T>>, T> {
72        self.push_if_internal(val, cond, &Guard::new())
73    }
74
75    /// Returns a guarded reference to the newest entry.
76    ///
77    /// Returns `None` if the [`Stack`] is empty. The returned reference can survive as long as the
78    /// associated [`Guard`] is alive.
79    ///
80    /// # Examples
81    ///
82    /// ```
83    /// use sdd::{Guard, Stack};
84    ///
85    /// let stack: Stack<usize> = Stack::default();
86    ///
87    /// assert!(stack.peek(&Guard::new()).is_none());
88    ///
89    /// stack.push(37);
90    /// stack.push(3);
91    ///
92    /// assert_eq!(**stack.peek(&Guard::new()).unwrap(), 3);
93    /// ```
94    #[inline]
95    pub fn peek<'g>(&self, guard: &'g Guard) -> Option<&'g LinkedEntry<T>> {
96        self.cleanup_newest(self.newest.load(Acquire, guard), guard)
97            .as_ref()
98    }
99}
100
101impl<T> Stack<T> {
102    /// Creates an empty [`Stack`].
103    ///
104    /// # Examples
105    ///
106    /// ```
107    /// use sdd::Stack;
108    ///
109    /// let stack: Stack<usize> = Stack::new();
110    ///```
111    #[cfg(not(feature = "loom"))]
112    #[inline]
113    #[must_use]
114    pub const fn new() -> Self {
115        Self {
116            newest: AtomicShared::null(),
117        }
118    }
119
120    /// Creates an empty [`Stack`].
121    #[cfg(feature = "loom")]
122    #[inline]
123    #[must_use]
124    pub fn new() -> Self {
125        Self {
126            newest: AtomicShared::null(),
127        }
128    }
129
130    /// Pushes an instance of `T` without checking the lifetime of `T`.
131    ///
132    /// Returns a [`Shared`] holding a strong reference to the newly pushed entry.
133    ///
134    /// # Safety
135    ///
136    /// `T::drop` can be run after the [`Stack`] is dropped, therefore it is safe only if `T::drop`
137    /// does not access short-lived data or [`std::mem::needs_drop`] is `false` for `T`.
138    ///
139    /// # Examples
140    ///
141    /// ```
142    /// use sdd::Stack;
143    ///
144    /// let hello = String::from("hello");
145    /// let stack: Stack<&str> = Stack::default();
146    ///
147    /// assert_eq!(unsafe { **stack.push_unchecked(hello.as_str()) }, "hello");
148    /// ```
149    #[inline]
150    pub unsafe fn push_unchecked(&self, val: T) -> Shared<LinkedEntry<T>> {
151        match self.push_if_internal(val, |_| true, &Guard::new()) {
152            Ok(entry) => entry,
153            Err(_) => {
154                unreachable!();
155            }
156        }
157    }
158
159    /// Pushes an instance of `T` if the newest entry satisfies the given condition without
160    /// checking the lifetime of `T`.
161    ///
162    /// # Errors
163    ///
164    /// Returns an error containing the supplied instance if the condition is not met.
165    ///
166    /// # Safety
167    ///
168    /// `T::drop` can be run after the [`Stack`] is dropped, therefore it is safe only if `T::drop`
169    /// does not access short-lived data or [`std::mem::needs_drop`] is `false` for `T`.
170    ///
171    /// # Examples
172    ///
173    /// ```
174    /// use sdd::Stack;
175    ///
176    /// let hello = String::from("hello");
177    /// let stack: Stack<&str> = Stack::default();
178    ///
179    /// assert!(unsafe { stack.push_if_unchecked(hello.as_str(), |e| e.is_none()).is_ok() });
180    /// ```
181    #[inline]
182    pub unsafe fn push_if_unchecked<F: FnMut(Option<&LinkedEntry<T>>) -> bool>(
183        &self,
184        val: T,
185        cond: F,
186    ) -> Result<Shared<LinkedEntry<T>>, T> {
187        self.push_if_internal(val, cond, &Guard::new())
188    }
189
190    /// Pops the newest entry.
191    ///
192    /// Returns `None` if the [`Stack`] is empty.
193    ///
194    /// # Examples
195    ///
196    /// ```
197    /// use sdd::Stack;
198    ///
199    /// let stack: Stack<usize> = Stack::default();
200    ///
201    /// stack.push(37);
202    /// stack.push(3);
203    /// stack.push(1);
204    ///
205    /// assert_eq!(stack.pop().map(|e| **e), Some(1));
206    /// assert_eq!(stack.pop().map(|e| **e), Some(3));
207    /// assert_eq!(stack.pop().map(|e| **e), Some(37));
208    /// assert!(stack.pop().is_none());
209    /// ```
210    #[inline]
211    pub fn pop(&self) -> Option<Shared<LinkedEntry<T>>> {
212        match self.pop_if(|_| true) {
213            Ok(result) => result,
214            Err(_) => unreachable!(),
215        }
216    }
217
218    /// Pops all the entries at once and returns them as a new [`Stack`].
219    ///
220    /// # Examples
221    ///
222    /// ```
223    /// use sdd::Stack;
224    ///
225    /// let stack: Stack<usize> = Stack::default();
226    ///
227    /// stack.push(37);
228    /// stack.push(3);
229    ///
230    /// let popped = stack.pop_all();
231    ///
232    /// stack.push(1);
233    ///
234    /// assert_eq!(stack.pop().map(|e| **e), Some(1));
235    /// assert!(stack.pop().is_none());
236    /// assert!(stack.is_empty());
237    ///
238    /// assert_eq!(popped.pop().map(|e| **e), Some(3));
239    /// assert_eq!(popped.pop().map(|e| **e), Some(37));
240    /// assert!(popped.pop().is_none());
241    /// ```
242    #[inline]
243    #[must_use]
244    pub fn pop_all(&self) -> Self {
245        let head = self.newest.swap((None, Tag::None), AcqRel).0;
246        Self {
247            newest: head.map_or_else(AtomicShared::default, AtomicShared::from),
248        }
249    }
250
251    /// Pops the newest entry if the entry satisfies the given condition.
252    ///
253    /// Returns `None` if the [`Stack`] is empty.
254    ///
255    /// # Errors
256    ///
257    /// Returns an error along with the newest entry if the given condition is not met.
258    ///
259    /// # Examples
260    ///
261    /// ```
262    /// use sdd::Stack;
263    ///
264    /// let stack: Stack<usize> = Stack::default();
265    ///
266    /// stack.push(3);
267    /// stack.push(1);
268    ///
269    /// assert!(stack.pop_if(|v| **v == 3).is_err());
270    /// assert_eq!(stack.pop().map(|e| **e), Some(1));
271    /// assert_eq!(stack.pop_if(|v| **v == 3).ok().and_then(|e| e).map(|e| **e), Some(3));
272    ///
273    /// assert!(stack.is_empty());
274    /// ```
275    #[inline]
276    pub fn pop_if<F: FnMut(&LinkedEntry<T>) -> bool>(
277        &self,
278        mut cond: F,
279    ) -> Result<Option<Shared<LinkedEntry<T>>>, Shared<LinkedEntry<T>>> {
280        let guard = Guard::new();
281        let mut newest_ptr = self.cleanup_newest(self.newest.load(Acquire, &guard), &guard);
282        while !newest_ptr.is_null() {
283            if let Some(newest_entry) = newest_ptr.get_shared() {
284                if !newest_entry.is_deleted(Relaxed) && !cond(&*newest_entry) {
285                    return Err(newest_entry);
286                }
287                if newest_entry.delete_self(Relaxed) {
288                    self.cleanup_newest(newest_ptr, &guard);
289                    return Ok(Some(newest_entry));
290                }
291            }
292            newest_ptr = self.cleanup_newest(newest_ptr, &guard);
293        }
294        Ok(None)
295    }
296
297    /// Peeks the newest entry.
298    ///
299    /// # Examples
300    ///
301    /// ```
302    /// use sdd::Stack;
303    ///
304    /// let stack: Stack<usize> = Stack::default();
305    ///
306    /// assert!(stack.peek_with(|v| v.is_none()));
307    ///
308    /// stack.push(37);
309    /// stack.push(3);
310    ///
311    /// assert_eq!(stack.peek_with(|v| **v.unwrap()), 3);
312    /// ```
313    #[inline]
314    pub fn peek_with<R, F: FnOnce(Option<&LinkedEntry<T>>) -> R>(&self, reader: F) -> R {
315        let guard = Guard::new();
316        reader(
317            self.cleanup_newest(self.newest.load(Acquire, &guard), &guard)
318                .as_ref(),
319        )
320    }
321
322    /// Returns the number of entries in the [`Stack`].
323    ///
324    /// This method iterates over all the entries in the [`Stack`] to count them, therefore its
325    /// time complexity is `O(N)`.
326    ///
327    /// # Examples
328    ///
329    /// ```
330    /// use sdd::Stack;
331    ///
332    /// let stack: Stack<usize> = Stack::default();
333    /// assert_eq!(stack.len(), 0);
334    ///
335    /// stack.push(7);
336    /// stack.push(11);
337    /// assert_eq!(stack.len(), 2);
338    ///
339    /// stack.pop();
340    /// stack.pop();
341    /// assert_eq!(stack.len(), 0);
342    /// ```
343    #[inline]
344    pub fn len(&self) -> usize {
345        self.iter(&Guard::new()).count()
346    }
347
348    /// Returns `true` if the [`Stack`] is empty.
349    ///
350    /// # Examples
351    ///
352    /// ```
353    /// use sdd::Stack;
354    ///
355    /// let stack: Stack<usize> = Stack::default();
356    /// assert!(stack.is_empty());
357    ///
358    /// stack.push(7);
359    /// assert!(!stack.is_empty());
360    /// ```
361    #[inline]
362    pub fn is_empty(&self) -> bool {
363        let guard = Guard::new();
364        self.cleanup_newest(self.newest.load(Acquire, &guard), &guard)
365            .is_null()
366    }
367
368    /// Returns an [`Iter`].
369    ///
370    /// # Examples
371    ///
372    /// ```
373    /// use sdd::{Guard, Stack};
374    ///
375    /// let stack: Stack<usize> = Stack::default();
376    /// assert_eq!(stack.iter(&Guard::new()).count(), 0);
377    ///
378    /// stack.push(7);
379    /// stack.push(11);
380    /// stack.push(17);
381    ///
382    /// let guard = Guard::new();
383    /// let mut iter = stack.iter(&guard);
384    /// assert_eq!(*iter.next().unwrap(), 17);
385    /// assert_eq!(*iter.next().unwrap(), 11);
386    /// assert_eq!(*iter.next().unwrap(), 7);
387    /// assert!(iter.next().is_none());
388    /// ```
389    #[inline]
390    pub fn iter<'g>(&self, guard: &'g Guard) -> Iter<'g, T> {
391        Iter {
392            current: self.cleanup_newest(self.newest.load(Acquire, guard), guard),
393            guard,
394        }
395    }
396
397    /// Pushes an entry into the [`Stack`].
398    fn push_if_internal<F: FnMut(Option<&LinkedEntry<T>>) -> bool>(
399        &self,
400        val: T,
401        mut cond: F,
402        guard: &Guard,
403    ) -> Result<Shared<LinkedEntry<T>>, T> {
404        let mut newest_ptr = self.cleanup_newest(self.newest.load(Acquire, guard), guard);
405        if !cond(newest_ptr.as_ref()) {
406            // The condition is not met.
407            return Err(val);
408        }
409
410        let mut new_entry = unsafe { Shared::new_with_unchecked(|| LinkedEntry::new(val)) };
411        loop {
412            new_entry
413                .next()
414                .swap((newest_ptr.get_shared(), Tag::None), Acquire);
415            let result = self.newest.compare_exchange(
416                newest_ptr,
417                (Some(new_entry.clone()), Tag::None),
418                AcqRel,
419                Acquire,
420                guard,
421            );
422            match result {
423                Ok(_) => return Ok(new_entry),
424                Err((_, actual_ptr)) => {
425                    newest_ptr = self.cleanup_newest(actual_ptr, guard);
426                    if !cond(newest_ptr.as_ref()) {
427                        // The condition is not met.
428                        break;
429                    }
430                }
431            }
432        }
433
434        // Extract the instance from the temporary entry.
435        Err(unsafe { new_entry.get_mut().unwrap_unchecked().take_inner() })
436    }
437
438    /// Cleans up logically removed entries that are attached to `newest`.
439    fn cleanup_newest<'g>(
440        &self,
441        mut newest_ptr: Ptr<'g, LinkedEntry<T>>,
442        guard: &'g Guard,
443    ) -> Ptr<'g, LinkedEntry<T>> {
444        while let Some(newest_entry) = newest_ptr.as_ref() {
445            if newest_entry.is_deleted(Relaxed) {
446                match self.newest.compare_exchange(
447                    newest_ptr,
448                    (newest_entry.next_shared(Acquire, guard), Tag::None),
449                    AcqRel,
450                    Acquire,
451                    guard,
452                ) {
453                    Ok((_, ptr)) | Err((_, ptr)) => newest_ptr = ptr,
454                }
455            } else {
456                break;
457            }
458        }
459        newest_ptr
460    }
461}
462
463impl<T: Clone> Clone for Stack<T> {
464    #[inline]
465    fn clone(&self) -> Self {
466        let self_clone = Self::default();
467        let guard = Guard::new();
468        let mut current = self.newest.load(Acquire, &guard);
469        let mut oldest: Option<Shared<LinkedEntry<T>>> = None;
470        while let Some(entry) = current.as_ref() {
471            let new_entry =
472                unsafe { Shared::new_with_unchecked(|| LinkedEntry::new((**entry).clone())) };
473            if let Some(oldest) = oldest.take() {
474                oldest
475                    .next()
476                    .swap((Some(new_entry.clone()), Tag::None), Acquire);
477            } else {
478                self_clone
479                    .newest
480                    .swap((Some(new_entry.clone()), Tag::None), Acquire);
481            }
482            oldest.replace(new_entry);
483            current = entry.next_ptr(Acquire, &guard);
484        }
485        self_clone
486    }
487}
488
489impl<T: Debug> Debug for Stack<T> {
490    #[inline]
491    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
492        let mut d = f.debug_set();
493        let guard = Guard::new();
494        let mut current = self.newest.load(Acquire, &guard);
495        while let Some(entry) = current.as_ref() {
496            let next = entry.next_ptr(Acquire, &guard);
497            d.entry(entry);
498            current = next;
499        }
500        d.finish()
501    }
502}
503
504impl<T> Default for Stack<T> {
505    #[inline]
506    fn default() -> Self {
507        Self::new()
508    }
509}
510
511impl<T> Drop for Stack<T> {
512    #[inline]
513    fn drop(&mut self) {
514        if !self.newest.is_null(Relaxed) {
515            let guard = Guard::new();
516            let mut iter = self.iter(&guard);
517            while let Some(entry) = iter.current.as_ref() {
518                entry.delete_self(Relaxed);
519                iter.next();
520            }
521        }
522        for _ in 0..4 {
523            Guard::new().accelerate();
524        }
525    }
526}
527
528impl<T: 'static> FromIterator<T> for Stack<T> {
529    #[inline]
530    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
531        let into_iter = iter.into_iter();
532        let stack = Self::default();
533        into_iter.for_each(|v| {
534            stack.push(v);
535        });
536        stack
537    }
538}
539
540impl<T> FusedIterator for Iter<'_, T> {}
541
542impl<'g, T> Iterator for Iter<'g, T> {
543    type Item = &'g T;
544
545    #[inline]
546    fn next(&mut self) -> Option<Self::Item> {
547        if let Some(current) = self.current.as_ref() {
548            self.current = current.next_ptr(Acquire, self.guard);
549            Some(current)
550        } else {
551            None
552        }
553    }
554}