• 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 #![cfg_attr(feature = "ffrt", allow(unused))]
22 
23 use std::ptr::NonNull;
24 
25 #[derive(Default)]
26 #[repr(C)]
27 pub(crate) struct Node<T> {
28     prev: Option<NonNull<T>>,
29     next: Option<NonNull<T>>,
30 }
31 
32 impl<T> Node<T> {
new() -> Node<T>33     pub(crate) fn new() -> Node<T> {
34         Node {
35             prev: None,
36             next: None,
37         }
38     }
39 }
40 
41 impl<T: Link> Node<T> {
remove_node(node: NonNull<T>) -> Option<NonNull<T>>42     unsafe fn remove_node(node: NonNull<T>) -> Option<NonNull<T>> {
43         let prev = T::node(node).as_ref().prev;
44         let next = T::node(node).as_ref().next;
45         match prev {
46             None => return None,
47             Some(prev) => T::node(prev).as_mut().next = next,
48         }
49         match next {
50             None => return None,
51             Some(next) => T::node(next).as_mut().prev = prev,
52         }
53         T::node(node).as_mut().prev = None;
54         T::node(node).as_mut().next = None;
55         Some(node)
56     }
57 }
58 
59 unsafe impl<T: Send> Send for Node<T> {}
60 unsafe impl<T: Sync> Sync for Node<T> {}
61 
62 pub(crate) struct LinkedList<L: Link + Default> {
63     head: NonNull<L>,
64 }
65 
66 unsafe impl<L: Link + Default + Send> Send for LinkedList<L> {}
67 unsafe impl<L: Link + Default + Sync> Sync for LinkedList<L> {}
68 
69 /// Defines the structure of a linked list node.
70 /// Provides methods for converting between nodes and instances.
71 ///
72 /// # Safety
73 ///
74 /// The implementation must ensure that the inserted data does not move in
75 /// memory.
76 pub(crate) unsafe trait Link {
node(ptr: NonNull<Self>) -> NonNull<Node<Self>> where Self: Sized77     unsafe fn node(ptr: NonNull<Self>) -> NonNull<Node<Self>>
78     where
79         Self: Sized;
80 }
81 
82 impl<L: Link + Default> LinkedList<L> {
83     /// Constructs a new linked list.
new() -> LinkedList<L>84     pub(crate) fn new() -> LinkedList<L> {
85         let head = Box::<L>::default();
86         let head_ptr = unsafe { NonNull::new_unchecked(Box::into_raw(head)) };
87         let node = unsafe { L::node(head_ptr).as_mut() };
88         node.prev = Some(head_ptr);
89         node.next = Some(head_ptr);
90         LinkedList { head: head_ptr }
91     }
92 
93     /// Inserts an element to the front of the list.
push_front(&mut self, val: NonNull<L>)94     pub(crate) fn push_front(&mut self, val: NonNull<L>) {
95         unsafe {
96             let head = L::node(self.head).as_mut();
97             L::node(val).as_mut().next = head.next;
98             L::node(val).as_mut().prev = Some(self.head);
99 
100             let node = Some(val);
101             if let Some(first) = head.next {
102                 L::node(first).as_mut().prev = node;
103             }
104             head.next = node;
105         }
106     }
107 
108     /// Pops an element from the back of the list.
109     #[cfg(feature = "time")]
pop_back(&mut self) -> Option<NonNull<L>>110     pub(crate) fn pop_back(&mut self) -> Option<NonNull<L>> {
111         unsafe {
112             let head = L::node(self.head).as_mut();
113             if head.prev != Some(self.head) {
114                 let node = head.prev.take().unwrap();
115                 Node::remove_node(node);
116                 Some(node)
117             } else {
118                 None
119             }
120         }
121     }
122 
123     /// Deletes an element in list.
124     ///
125     /// # Safety
126     ///
127     /// This method can be safely used when the node is in a guarded linked list
128     /// that the caller has unique access to or the node is not in any
129     /// linked list.
remove(&mut self, node: NonNull<L>) -> Option<NonNull<L>>130     pub(crate) unsafe fn remove(&mut self, node: NonNull<L>) -> Option<NonNull<L>> {
131         Node::remove_node(node)
132     }
133 
134     /// Checks whether the list is empty.
135     #[cfg(feature = "time")]
is_empty(&self) -> bool136     pub(crate) fn is_empty(&self) -> bool {
137         unsafe { L::node(self.head).as_ref().next == Some(self.head) }
138     }
139 
140     /// Traverses the list and applies the closure on each element. If the
141     /// element meets the condition, removes it from the list.
142     #[cfg(feature = "net")]
drain_filtered<F>(&mut self, mut f: F) where F: FnMut(&mut L) -> bool,143     pub(crate) fn drain_filtered<F>(&mut self, mut f: F)
144     where
145         F: FnMut(&mut L) -> bool,
146     {
147         unsafe {
148             let head = L::node(self.head).as_ref();
149             let mut p = head.next;
150             while p != Some(self.head) {
151                 let node = p.unwrap();
152                 let next = L::node(node).as_ref().next;
153                 if f(&mut *node.as_ptr()) {
154                     Node::remove_node(node);
155                 }
156                 p = next;
157             }
158         }
159     }
160 }
161 
162 impl<L: Link + Default> Default for LinkedList<L> {
default() -> Self163     fn default() -> Self {
164         LinkedList::new()
165     }
166 }
167 
168 impl<L: Link + Default> Drop for LinkedList<L> {
drop(&mut self)169     fn drop(&mut self) {
170         let _ = unsafe { Box::from_raw(self.head.as_ptr()) };
171     }
172 }
173 
174 #[cfg(test)]
175 mod tests {
176     use std::ptr::{addr_of_mut, NonNull};
177 
178     use crate::util::linked_list::{Link, LinkedList, Node};
179 
180     #[derive(Default)]
181     struct Entry {
182         val: usize,
183         node: Node<Entry>,
184     }
185 
186     impl Entry {
new(val: usize) -> Entry187         fn new(val: usize) -> Entry {
188             Entry {
189                 val,
190                 node: Node::new(),
191             }
192         }
193 
get_ptr(&self) -> NonNull<Self>194         fn get_ptr(&self) -> NonNull<Self> {
195             NonNull::from(self)
196         }
197     }
198 
address_of_node(mut ptr: NonNull<Entry>) -> NonNull<Node<Entry>>199     unsafe fn address_of_node(mut ptr: NonNull<Entry>) -> NonNull<Node<Entry>> {
200         let node_ptr = addr_of_mut!(ptr.as_mut().node);
201         NonNull::new_unchecked(node_ptr)
202     }
203 
get_val(ptr: NonNull<Entry>) -> usize204     fn get_val(ptr: NonNull<Entry>) -> usize {
205         unsafe { ptr.as_ref().val }
206     }
207 
208     unsafe impl Link for Entry {
node(ptr: NonNull<Self>) -> NonNull<Node<Self>>209         unsafe fn node(ptr: NonNull<Self>) -> NonNull<Node<Self>> {
210             address_of_node(ptr)
211         }
212     }
213 
214     /// UT test cases for `is_empty()` and `clear()`.
215     ///
216     /// # Brief
217     /// 1. Create a linked list.
218     /// 2. Check if the list is empty before and after pushing nodes into the
219     /// list.
220     /// 3. Check if the list is empty before and after clear the list.
221     #[test]
222     #[cfg(feature = "time")]
ut_link_list_is_empty()223     fn ut_link_list_is_empty() {
224         let mut list = LinkedList::<Entry>::new();
225         assert!(list.is_empty());
226         let node1 = Entry::new(1);
227         let node1 = node1.get_ptr();
228         list.push_front(node1);
229         assert!(!list.is_empty());
230     }
231 
232     /// UT test cases for `push_front()` and `pop_back()`.
233     ///
234     /// # Brief
235     /// 1. Create a linked list.
236     /// 2. Push nodes into the list.
237     /// 3. Pop nodes from the list and check the value.
238     #[test]
239     #[cfg(feature = "time")]
ut_link_list_push_and_pop()240     fn ut_link_list_push_and_pop() {
241         let mut list = LinkedList::<Entry>::new();
242         assert!(list.is_empty());
243         let node1 = Entry::new(1);
244         let node1 = node1.get_ptr();
245         let node2 = Entry::new(2);
246         let node2 = node2.get_ptr();
247         let node3 = Entry::new(3);
248         let node3 = node3.get_ptr();
249         list.push_front(node1);
250         assert!(!list.is_empty());
251         list.push_front(node2);
252         list.push_front(node3);
253         assert_eq!(1, get_val(list.pop_back().unwrap()));
254         assert_eq!(2, get_val(list.pop_back().unwrap()));
255         assert_eq!(3, get_val(list.pop_back().unwrap()));
256         assert!(list.pop_back().is_none());
257         assert!(list.is_empty());
258     }
259 
260     /// UT test cases for `push_front()` and `remove()`.
261     ///
262     /// # Brief
263     /// 1. Create a linked list.
264     /// 2. Push nodes into the list.
265     /// 3. Remove the first node from the list and check the list.
266     /// 4. Remove the second node from the list and check the list.
267     /// 5. Remove the third node from the list and check the list.
268     #[test]
ut_link_list_remove()269     fn ut_link_list_remove() {
270         let mut list = LinkedList::<Entry>::new();
271         let node1 = Entry::new(1);
272         let node1_ptr = node1.get_ptr();
273         let node2 = Entry::new(2);
274         let node2_ptr = node2.get_ptr();
275         let node3 = Entry::new(3);
276         let node3_ptr = node3.get_ptr();
277         list.push_front(node1_ptr);
278         list.push_front(node2_ptr);
279         list.push_front(node3_ptr);
280         unsafe {
281             assert!(list.remove(node1_ptr).is_some());
282             assert!(list.remove(node1_ptr).is_none());
283             assert_eq!(Some(node2_ptr), node3.node.next);
284             assert_eq!(Some(node3_ptr), node2.node.prev);
285             assert!(list.remove(node2_ptr).is_some());
286             assert!(list.remove(node2_ptr).is_none());
287             assert!(list.remove(node3_ptr).is_some());
288             assert!(list.remove(node3_ptr).is_none());
289         }
290 
291         list.push_front(node1_ptr);
292         list.push_front(node2_ptr);
293         list.push_front(node3_ptr);
294         unsafe {
295             assert!(list.remove(node2_ptr).is_some());
296             assert!(list.remove(node2_ptr).is_none());
297             assert_eq!(Some(node1_ptr), node3.node.next);
298             assert_eq!(Some(node3_ptr), node1.node.prev);
299             assert!(list.remove(node1_ptr).is_some());
300             assert!(list.remove(node1_ptr).is_none());
301             assert!(list.remove(node3_ptr).is_some());
302             assert!(list.remove(node3_ptr).is_none());
303         }
304 
305         list.push_front(node1_ptr);
306         list.push_front(node2_ptr);
307         list.push_front(node3_ptr);
308         unsafe {
309             assert_eq!(get_val(list.remove(node3_ptr).unwrap()), 3);
310             assert!(list.remove(node3_ptr).is_none());
311             assert_eq!(Some(node1_ptr), node2.node.next);
312             assert_eq!(Some(node2_ptr), node1.node.prev);
313             assert_eq!(get_val(list.remove(node1_ptr).unwrap()), 1);
314             assert!(list.remove(node1_ptr).is_none());
315             assert_eq!(get_val(list.remove(node2_ptr).unwrap()), 2);
316             assert!(list.remove(node2_ptr).is_none());
317         }
318     }
319 
320     /// UT test cases for `drain_filtered()`.
321     ///
322     /// # Brief
323     /// 1. Create a linked list.
324     /// 2. Push nodes into the list.
325     /// 3. Drain filtered the list for node that contains a value of 2.
326     #[test]
327     #[cfg(all(feature = "net", feature = "time"))]
ut_link_list_for_each_mut()328     fn ut_link_list_for_each_mut() {
329         let mut list = LinkedList::<Entry>::new();
330         let node1 = Entry::new(1);
331         let node1_ptr = node1.get_ptr();
332         let node2 = Entry::new(2);
333         let node2_ptr = node2.get_ptr();
334         let node3 = Entry::new(3);
335         let node3_ptr = node3.get_ptr();
336         list.push_front(node1_ptr);
337         list.push_front(node2_ptr);
338         list.push_front(node3_ptr);
339 
340         let mut value = 0;
341         list.drain_filtered(|x| {
342             if x.val == 2 {
343                 value = x.val;
344                 return true;
345             }
346             false
347         });
348         assert_eq!(value, 2);
349         unsafe {
350             let node = list.pop_back();
351             assert_eq!(node.unwrap().as_mut().val, 1);
352             let node = list.pop_back();
353             assert_eq!(node.unwrap().as_mut().val, 3);
354             let node = list.pop_back();
355             assert_eq!(node, None);
356         }
357     }
358 }
359