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