heapless/pool/
treiber.rs

1use core::mem::ManuallyDrop;
2
3#[cfg_attr(target_arch = "x86", path = "treiber/cas.rs")]
4#[cfg_attr(arm_llsc, path = "treiber/llsc.rs")]
5mod impl_;
6
7pub use impl_::{AtomicPtr, NonNullPtr};
8
9pub struct Stack<N>
10where
11    N: Node,
12{
13    top: AtomicPtr<N>,
14}
15
16impl<N> Stack<N>
17where
18    N: Node,
19{
20    pub const fn new() -> Self {
21        Self {
22            top: AtomicPtr::null(),
23        }
24    }
25
26    /// # Safety
27    /// - `node` must be a valid pointer
28    /// - aliasing rules must be enforced by the caller. e.g, the same `node` may not be pushed more than once
29    pub unsafe fn push(&self, node: NonNullPtr<N>) {
30        impl_::push(self, node)
31    }
32
33    pub fn try_pop(&self) -> Option<NonNullPtr<N>> {
34        impl_::try_pop(self)
35    }
36}
37
38pub trait Node: Sized {
39    type Data;
40
41    fn next(&self) -> &AtomicPtr<Self>;
42    fn next_mut(&mut self) -> &mut AtomicPtr<Self>;
43}
44
45pub union UnionNode<T> {
46    next: ManuallyDrop<AtomicPtr<UnionNode<T>>>,
47    pub data: ManuallyDrop<T>,
48}
49
50impl<T> Node for UnionNode<T> {
51    type Data = T;
52
53    fn next(&self) -> &AtomicPtr<Self> {
54        unsafe { &self.next }
55    }
56
57    fn next_mut(&mut self) -> &mut AtomicPtr<Self> {
58        unsafe { &mut self.next }
59    }
60}
61
62pub struct StructNode<T> {
63    pub next: ManuallyDrop<AtomicPtr<StructNode<T>>>,
64    pub data: ManuallyDrop<T>,
65}
66
67impl<T> Node for StructNode<T> {
68    type Data = T;
69
70    fn next(&self) -> &AtomicPtr<Self> {
71        &self.next
72    }
73
74    fn next_mut(&mut self) -> &mut AtomicPtr<Self> {
75        &mut self.next
76    }
77}
78
79#[cfg(test)]
80mod tests {
81    use core::mem;
82
83    use super::*;
84
85    #[test]
86    fn node_is_never_zero_sized() {
87        struct Zst;
88
89        assert_ne!(mem::size_of::<UnionNode<Zst>>(), 0);
90    }
91}