lock_free_stack/
lock_free_stack.rs1use std::ptr;
2use std::sync::atomic::{AtomicPtr, Ordering};
3
4#[allow(dead_code)]
5struct Node<K> {
6 size: usize,
7 next: *mut Node<K>,
8 payload: K
9}
10
11#[allow(dead_code)]
12pub struct StackTailIterator<M> {
13 top: *mut Node<M>
14}
15
16#[allow(dead_code)]
17pub struct Stack<T> {
18 top: AtomicPtr<Node<T>>
19}
20
21impl<T> Stack<T> {
22 #[allow(dead_code)]
23 pub fn new() -> Stack<T> {
24 Stack { top: AtomicPtr::new(ptr::null_mut()) }
25 }
26
27 #[allow(dead_code)]
28 pub fn size(&self) -> usize {
29 let top_ptr = self.top.load(Ordering::Relaxed);
30 if top_ptr.is_null() {
31 0
32 } else {
33 unsafe { (&*top_ptr).size }
34 }
35 }
36
37 #[allow(dead_code)]
38 pub fn add(&self, value: T) -> usize {
39 let mut top_ptr = self.top.load(Ordering::Relaxed);
40
41 let new_top = Box::into_raw(Box::new(
42 Node { size: 0, next: ptr::null_mut(), payload: value }
43 ));
44
45 loop {
46 let new_size = if top_ptr.is_null() { 1 } else { unsafe { (&*top_ptr).size + 1 } };
47 unsafe {
48 (&mut *new_top).size = new_size;
49 (&mut *new_top).next = top_ptr;
50 };
51
52 let previous_top = self.top.compare_and_swap(
53 top_ptr,
54 new_top,
55 Ordering::Relaxed
56 );
57
58 if previous_top == top_ptr {
59 return new_size;
60 } else {
61 top_ptr = previous_top;
62 }
63 }
64 }
65
66 #[allow(dead_code)]
67 pub fn remove_all(&self) -> StackTailIterator<T> {
68 let mut top_ptr = self.top.load(Ordering::Relaxed);
69
70 loop {
71 let previous_top = self.top.compare_and_swap(
72 top_ptr,
73 ptr::null_mut(),
74 Ordering::Relaxed
75 );
76
77 if previous_top == top_ptr {
78 return StackTailIterator { top: top_ptr }
79 } else {
80 top_ptr = previous_top;
81 }
82 }
83 }
84}
85
86impl<T> Drop for Stack<T> {
87 fn drop(&mut self) {
88 let _ = self.remove_all();
89 }
90}
91
92impl<M> Iterator for StackTailIterator<M> {
93 type Item = M;
94
95 fn next(&mut self) -> Option<M> {
96 if self.top.is_null() {
97 None
98 } else {
99 let boxed_node = unsafe { Box::from_raw(self.top) };
100 self.top = boxed_node.next;
101
102 Some(boxed_node.payload)
103 }
104 }
105}
106
107impl<M> Drop for StackTailIterator<M> {
108 fn drop(&mut self) {
109 for _ in self {}
110 }
111}