• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 //! This linked list does not have ownership of nodes, and it treats the
15 //! structure passed in by the user as a node for storage, so the `clear`
16 //! operation does not release memory, and the `remove` operation needs to
17 //! ensure that the node is in any linked list held by a caller to ensure the
18 //! memory validity of pointers within the node. Users need to manage the memory
19 //! of the instances associated with each node themselves.
20 
21 use std::ptr::NonNull;
22 
23 #[derive(Default)]
24 #[repr(C)]
25 pub(crate) struct Node<T> {
26     prev: Option<NonNull<T>>,
27     next: Option<NonNull<T>>,
28 }
29 
30 impl<T> Node<T> {
new() -> Node<T>31     pub(crate) fn new() -> Node<T> {
32         Node {
33             prev: None,
34             next: None,
35         }
36     }
37 }
38 
39 impl<T: Link> Node<T> {
remove_node(node: NonNull<T>) -> Option<NonNull<T>>40     unsafe fn remove_node(node: NonNull<T>) -> Option<NonNull<T>> {
41         let prev = T::node(node).as_ref().prev;
42         let next = T::node(node).as_ref().next;
43         match prev {
44             None => return None,
45             Some(prev) => T::node(prev).as_mut().next = next,
46         }
47         match next {
48             None => return None,
49             Some(next) => T::node(next).as_mut().prev = prev,
50         }
51         T::node(node).as_mut().prev = None;
52         T::node(node).as_mut().next = None;
53         Some(node)
54     }
55 }
56 
57 unsafe impl<T: Send> Send for Node<T> {}
58 unsafe impl<T: Sync> Sync for Node<T> {}
59 
60 pub(crate) struct LinkedList<L: Link + Default> {
61     head: NonNull<L>,
62 }
63 
64 unsafe impl<L: Link + Default + Send> Send for LinkedList<L> {}
65 unsafe impl<L: Link + Default + Sync> Sync for LinkedList<L> {}
66 
67 /// Defines the structure of a linked list node.
68 /// Provides methods for converting between nodes and instances.
69 ///
70 /// # Safety
71 ///
72 /// The implementation must ensure that the inserted data does not move in
73 /// memory.
74 pub(crate) unsafe trait Link {
node(ptr: NonNull<Self>) -> NonNull<Node<Self>> where Self: Sized75     unsafe fn node(ptr: NonNull<Self>) -> NonNull<Node<Self>>
76     where
77         Self: Sized;
78 }
79 
80 impl<L: Link + Default> LinkedList<L> {
81     /// Constructs a new linked list.
new() -> LinkedList<L>82     pub(crate) fn new() -> LinkedList<L> {
83         let head = Box::<L>::default();
84         let head_ptr = unsafe { NonNull::new_unchecked(Box::into_raw(head)) };
85         let node = unsafe { L::node(head_ptr).as_mut() };
86         node.prev = Some(head_ptr);
87         node.next = Some(head_ptr);
88         LinkedList { head: head_ptr }
89     }
90 
91     /// Inserts an element to the front of the list.
push_front(&mut self, val: NonNull<L>)92     pub(crate) fn push_front(&mut self, val: NonNull<L>) {
93         unsafe {
94             let head = L::node(self.head).as_mut();
95             L::node(val).as_mut().next = head.next;
96             L::node(val).as_mut().prev = Some(self.head);
97 
98             let node = Some(val);
99             if let Some(first) = head.next {
100                 L::node(first).as_mut().prev = node;
101             }
102             head.next = node;
103         }
104     }
105 
106     /// Pops an element from the back of the list.
107     #[cfg(feature = "time")]
pop_back(&mut self) -> Option<NonNull<L>>108     pub(crate) fn pop_back(&mut self) -> Option<NonNull<L>> {
109         unsafe {
110             let head = L::node(self.head).as_mut();
111             if head.prev != Some(self.head) {
112                 let node = head.prev.take().unwrap();
113                 Node::remove_node(node);
114                 Some(node)
115             } else {
116                 None
117             }
118         }
119     }
120 
121     /// Deletes an element in list.
122     ///
123     /// # Safety
124     ///
125     /// This method can be safely used when the node is in a guarded linked list
126     /// that the caller has unique access to or the node is not in any
127     /// linked list.
remove(&mut self, node: NonNull<L>) -> Option<NonNull<L>>128     pub(crate) unsafe fn remove(&mut self, node: NonNull<L>) -> Option<NonNull<L>> {
129         Node::remove_node(node)
130     }
131 
132     /// Checks whether the list is empty.
133     #[cfg(feature = "time")]
is_empty(&self) -> bool134     pub(crate) fn is_empty(&self) -> bool {
135         unsafe { L::node(self.head).as_ref().next == Some(self.head) }
136     }
137 
138     /// Traverses the list and execute the closure.
139     #[cfg(feature = "net")]
for_each_mut<F>(&mut self, mut f: F) where F: FnMut(&mut L),140     pub(crate) fn for_each_mut<F>(&mut self, mut f: F)
141     where
142         F: FnMut(&mut L),
143     {
144         unsafe {
145             let head = L::node(self.head).as_ref();
146             let mut p = head.next;
147             while p != Some(self.head) {
148                 let node = p.unwrap();
149                 f(&mut *node.as_ptr());
150                 p = L::node(node).as_ref().next;
151             }
152         }
153     }
154 }
155 
156 impl<L: Link + Default> Default for LinkedList<L> {
default() -> Self157     fn default() -> Self {
158         LinkedList::new()
159     }
160 }
161 
162 impl<L: Link + Default> Drop for LinkedList<L> {
drop(&mut self)163     fn drop(&mut self) {
164         let _ = unsafe { Box::from_raw(self.head.as_ptr()) };
165     }
166 }
167 
168 #[cfg(test)]
169 mod tests {
170     use std::ptr::{addr_of_mut, NonNull};
171 
172     use crate::util::linked_list::{Link, LinkedList, Node};
173 
174     #[derive(Default)]
175     struct Entry {
176         val: usize,
177         node: Node<Entry>,
178     }
179 
180     impl Entry {
new(val: usize) -> Entry181         fn new(val: usize) -> Entry {
182             Entry {
183                 val,
184                 node: Node::new(),
185             }
186         }
187 
get_ptr(&self) -> NonNull<Self>188         fn get_ptr(&self) -> NonNull<Self> {
189             NonNull::from(self)
190         }
191     }
192 
address_of_node(mut ptr: NonNull<Entry>) -> NonNull<Node<Entry>>193     unsafe fn address_of_node(mut ptr: NonNull<Entry>) -> NonNull<Node<Entry>> {
194         let node_ptr = addr_of_mut!(ptr.as_mut().node);
195         NonNull::new_unchecked(node_ptr)
196     }
197 
get_val(ptr: NonNull<Entry>) -> usize198     fn get_val(ptr: NonNull<Entry>) -> usize {
199         unsafe { ptr.as_ref().val }
200     }
201 
202     unsafe impl Link for Entry {
node(ptr: NonNull<Self>) -> NonNull<Node<Self>>203         unsafe fn node(ptr: NonNull<Self>) -> NonNull<Node<Self>> {
204             address_of_node(ptr)
205         }
206     }
207 
208     /// UT test cases for `is_empty()` and `clear()`.
209     ///
210     /// # Brief
211     /// 1. Create a linked list.
212     /// 2. Check if the list is empty before and after pushing nodes into the
213     /// list.
214     /// 3. Check if the list is empty before and after clear the list.
215     #[test]
ut_link_list_is_empty()216     fn ut_link_list_is_empty() {
217         let mut list = LinkedList::<Entry>::new();
218         assert!(list.is_empty());
219         let node1 = Entry::new(1);
220         let node1 = node1.get_ptr();
221         list.push_front(node1);
222         assert!(!list.is_empty());
223     }
224 
225     /// UT test cases for `push_front()` and `pop_back()`.
226     ///
227     /// # Brief
228     /// 1. Create a linked list.
229     /// 2. Push nodes into the list.
230     /// 3. Pop nodes from the list and check the value.
231     #[test]
ut_link_list_push_and_pop()232     fn ut_link_list_push_and_pop() {
233         let mut list = LinkedList::<Entry>::new();
234         assert!(list.is_empty());
235         let node1 = Entry::new(1);
236         let node1 = node1.get_ptr();
237         let node2 = Entry::new(2);
238         let node2 = node2.get_ptr();
239         let node3 = Entry::new(3);
240         let node3 = node3.get_ptr();
241         list.push_front(node1);
242         assert!(!list.is_empty());
243         list.push_front(node2);
244         list.push_front(node3);
245         assert_eq!(1, get_val(list.pop_back().unwrap()));
246         assert_eq!(2, get_val(list.pop_back().unwrap()));
247         assert_eq!(3, get_val(list.pop_back().unwrap()));
248         assert!(list.pop_back().is_none());
249         assert!(list.is_empty());
250     }
251 
252     /// UT test cases for `push_front()` and `remove()`.
253     ///
254     /// # Brief
255     /// 1. Create a linked list.
256     /// 2. Push nodes into the list.
257     /// 3. Remove the first node from the list and check the list.
258     /// 4. Remove the second node from the list and check the list.
259     /// 5. Remove the third node from the list and check the list.
260     #[test]
ut_link_list_remove()261     fn ut_link_list_remove() {
262         let mut list = LinkedList::<Entry>::new();
263         assert!(list.is_empty());
264         let node1 = Entry::new(1);
265         let node1_ptr = node1.get_ptr();
266         let node2 = Entry::new(2);
267         let node2_ptr = node2.get_ptr();
268         let node3 = Entry::new(3);
269         let node3_ptr = node3.get_ptr();
270         list.push_front(node1_ptr);
271         assert!(!list.is_empty());
272         list.push_front(node2_ptr);
273         list.push_front(node3_ptr);
274         unsafe {
275             assert!(list.remove(node1_ptr).is_some());
276             assert!(list.remove(node1_ptr).is_none());
277             assert_eq!(Some(node2_ptr), node3.node.next);
278             assert_eq!(Some(node3_ptr), node2.node.prev);
279             assert!(list.remove(node2_ptr).is_some());
280             assert!(list.remove(node2_ptr).is_none());
281             assert!(list.remove(node3_ptr).is_some());
282             assert!(list.remove(node3_ptr).is_none());
283         }
284 
285         list.push_front(node1_ptr);
286         list.push_front(node2_ptr);
287         list.push_front(node3_ptr);
288         unsafe {
289             assert!(list.remove(node2_ptr).is_some());
290             assert!(list.remove(node2_ptr).is_none());
291             assert_eq!(Some(node1_ptr), node3.node.next);
292             assert_eq!(Some(node3_ptr), node1.node.prev);
293             assert!(list.remove(node1_ptr).is_some());
294             assert!(list.remove(node1_ptr).is_none());
295             assert!(list.remove(node3_ptr).is_some());
296             assert!(list.remove(node3_ptr).is_none());
297         }
298 
299         list.push_front(node1_ptr);
300         list.push_front(node2_ptr);
301         list.push_front(node3_ptr);
302         unsafe {
303             assert!(list.remove(node3_ptr).is_some());
304             assert!(list.remove(node3_ptr).is_none());
305             assert_eq!(Some(node1_ptr), node2.node.next);
306             assert_eq!(Some(node2_ptr), node1.node.prev);
307             assert!(list.remove(node1_ptr).is_some());
308             assert!(list.remove(node1_ptr).is_none());
309             assert!(list.remove(node2_ptr).is_some());
310             assert!(list.remove(node2_ptr).is_none());
311         }
312         assert!(list.is_empty());
313     }
314 
315     /// UT test cases for `for_each_mut()`.
316     ///
317     /// # Brief
318     /// 1. Create a linked list.
319     /// 2. Push nodes into the list.
320     /// 3. Check the value in node after traversing the list.
321     #[test]
ut_link_list_for_each_mut()322     fn ut_link_list_for_each_mut() {
323         let mut list = LinkedList::<Entry>::new();
324         assert!(list.is_empty());
325         let node1 = Entry::new(1);
326         let node1 = node1.get_ptr();
327         let node2 = Entry::new(2);
328         let node2 = node2.get_ptr();
329         let node3 = Entry::new(3);
330         let node3 = node3.get_ptr();
331         list.push_front(node1);
332         list.push_front(node2);
333         list.push_front(node3);
334         list.for_each_mut(|entry| {
335             entry.val += 1;
336         });
337         assert_eq!(2, get_val(list.pop_back().unwrap()));
338         assert_eq!(3, get_val(list.pop_back().unwrap()));
339         assert_eq!(4, get_val(list.pop_back().unwrap()));
340         assert!(list.pop_back().is_none());
341         assert!(list.is_empty());
342     }
343 }
344