ach_linked/
lib.rs

1#![no_std]
2use core::marker::PhantomPinned;
3use core::ops::{Deref, DerefMut};
4use core::ptr::{self, NonNull};
5use core::sync::atomic::{AtomicPtr, Ordering::Relaxed};
6
7pub struct Node<T> {
8    val: T,
9    next: Option<NonNull<Node<T>>>,
10    _pin: PhantomPinned,
11}
12impl<T> Node<T> {
13    pub const fn new(val: T) -> Self {
14        Self {
15            val,
16            next: None,
17            _pin: PhantomPinned,
18        }
19    }
20    pub fn next<'b>(&mut self) -> Option<&'b mut Node<T>> {
21        unsafe { Some(self.next?.as_mut()) }
22    }
23    pub fn take_next<'b>(&mut self) -> Option<&'b mut Node<T>> {
24        unsafe { Some(self.next.take()?.as_mut()) }
25    }
26    pub fn last(&mut self) -> &mut Node<T> {
27        let mut now = self;
28        loop {
29            if let Some(next) = &mut now.next {
30                now = unsafe { next.as_mut() };
31            } else {
32                return now;
33            }
34        }
35    }
36    /// Adds a node to the LinkedList.
37    ///  
38    /// # Safety
39    /// This function is only safe as long as `node` is guaranteed to
40    /// get removed from the list before it gets moved or dropped.
41    pub unsafe fn push(&mut self, node: &mut Node<T>) {
42        assert!(node.next.is_none());
43        node.next = self.next;
44        self.next = Some(node.into());
45    }
46    /// Adds a list to the LinkedList.
47    ///
48    /// # Safety
49    /// This function is only safe as long as `node` is guaranteed to
50    /// get removed from the list before it gets moved or dropped.
51    pub unsafe fn push_list(&mut self, node: &mut Node<T>) {
52        let last = node.last() as *mut Node<T>;
53        (*last).next = self.next;
54        self.next = Some(node.into());
55    }
56    /// remove child which eq node.
57    ///
58    /// Notice: can't remove head node.
59    pub fn remove_node(&mut self, node: &mut Node<T>) -> bool {
60        let mut now = self;
61        loop {
62            if let Some(next) = &mut now.next {
63                let next = unsafe { next.as_mut() };
64                if core::ptr::eq(next, node) {
65                    now.next = next.next;
66                    return true;
67                }
68                now = next;
69            } else {
70                return false;
71            }
72        }
73    }
74    pub fn into_iter(&mut self) -> NodeIter<'_, T> {
75        NodeIter { node: Some(self) }
76    }
77}
78impl<T> Deref for Node<T> {
79    type Target = T;
80    fn deref(&self) -> &Self::Target {
81        &self.val
82    }
83}
84impl<T> DerefMut for Node<T> {
85    fn deref_mut(&mut self) -> &mut Self::Target {
86        &mut self.val
87    }
88}
89
90pub struct NodeIter<'a, T> {
91    node: Option<&'a mut Node<T>>,
92}
93impl<'a, T> Iterator for NodeIter<'a, T> {
94    type Item = &'a mut Node<T>;
95    fn next(&mut self) -> Option<Self::Item> {
96        let node = self.node.as_mut().map(|x| *x as *mut Node<T>);
97        if let Some(node) = node.map(|x| unsafe { &mut *x }) {
98            let next = node.take_next();
99            self.node = next;
100            Some(node)
101        } else {
102            None
103        }
104    }
105}
106
107pub struct LinkedList<T> {
108    head: AtomicPtr<Node<T>>,
109    will_remove: [AtomicPtr<Node<T>>; 4],
110}
111impl<T> Default for LinkedList<T> {
112    fn default() -> Self {
113        Self::new()
114    }
115}
116impl<T> LinkedList<T> {
117    #[allow(clippy::declare_interior_mutable_const)]
118    const NONE_NODE: AtomicPtr<Node<T>> = AtomicPtr::new(ptr::null_mut());
119    pub const fn new() -> Self {
120        Self {
121            head: Self::NONE_NODE,
122            will_remove: [Self::NONE_NODE; 4],
123        }
124    }
125
126    pub fn is_empty(&self) -> bool {
127        let head = self.head.load(Relaxed);
128        head.is_null()
129    }
130
131    /// delete all entries from LinkedList
132    ///
133    /// If list is empty, return NULL, otherwise, delete all entries and return the pointer to the first entry.
134    #[allow(clippy::mut_from_ref)]
135    pub fn take_all(&self) -> Option<&mut Node<T>> {
136        unsafe { self.head.swap(ptr::null_mut(), Relaxed).as_mut() }
137    }
138
139    /// Adds a node to the LinkedList.
140    ///  
141    /// # Safety
142    /// This function is only safe as long as `node` is guaranteed to
143    /// get removed from the list before it gets moved or dropped.
144    pub unsafe fn push(&self, node: &mut Node<T>) {
145        assert!(node.next.is_none());
146        self.head
147            .fetch_update(Relaxed, Relaxed, |p| {
148                node.next = p.as_mut().map(|x| x.into());
149                Some(node)
150            })
151            .unwrap();
152    }
153    /// Adds a list to the LinkedList.
154    ///
155    /// # Safety
156    /// This function is only safe as long as `node` is guaranteed to
157    /// get removed from the list before it gets moved or dropped.
158    pub unsafe fn push_list(&self, node: &mut Node<T>) {
159        let last = node.last() as *mut Node<T>;
160        self.head
161            .fetch_update(Relaxed, Relaxed, |p| {
162                (*last).next = p.as_mut().map(|x| x.into());
163                Some(node)
164            })
165            .unwrap();
166    }
167
168    /// Removes a node from the LinkedList.
169    pub fn remove(&self, node: &mut Node<T>) {
170        let my_node = loop {
171            let node = self.will_remove.iter().find(|x| {
172                x.compare_exchange(ptr::null_mut(), node as *mut _, Relaxed, Relaxed)
173                    .is_ok()
174            });
175            if let Some(node) = node {
176                break node;
177            }
178            spin_loop::spin();
179        };
180
181        let mut root = self.take_all();
182        loop {
183            while let Some(node) = &mut root {
184                let next = node.take_next();
185                if !self.will_remove.iter().any(|x| {
186                    x.compare_exchange((*node) as *mut _, ptr::null_mut(), Relaxed, Relaxed)
187                        .is_ok()
188                }) {
189                    unsafe { self.push(*node) };
190                }
191                root = next;
192            }
193            if !core::ptr::eq(my_node.load(Relaxed), node) {
194                return;
195            }
196            spin_loop::spin();
197            let new_root = self.take_all();
198            root = new_root;
199        }
200    }
201}