use std::ptr;
use std::sync::atomic::{AtomicPtr, Ordering};
pub struct Stack<T> {
head: AtomicPtr<Node<T>>,
}
struct Node<T> {
value: T,
next: *mut Node<T>,
}
impl<T> Stack<T> {
pub fn new() -> Self {
Self {
head: AtomicPtr::new(ptr::null_mut()),
}
}
pub fn push(&self, value: T) {
let node = Box::into_raw(Box::new(Node {
value,
next: ptr::null_mut(),
}));
loop {
let head = self.head.load(Ordering::Relaxed);
unsafe { (*node).next = head }
if self
.head
.compare_exchange(head, node, Ordering::Relaxed, Ordering::Relaxed)
.is_ok()
{
break;
}
}
}
pub fn drain(&mut self, mut f: impl FnMut(T)) {
let mut head = *self.head.get_mut();
while !head.is_null() {
let owned_head = unsafe { Box::from_raw(head) };
f(owned_head.value);
head = owned_head.next;
}
}
}