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}