1 #![cfg_attr(not(feature = "full"), allow(dead_code))] 2 3 //! An intrusive double linked list of data. 4 //! 5 //! The data structure supports tracking pinned nodes. Most of the data 6 //! structure's APIs are `unsafe` as they require the caller to ensure the 7 //! specified node is actually contained by the list. 8 9 use core::cell::UnsafeCell; 10 use core::fmt; 11 use core::marker::{PhantomData, PhantomPinned}; 12 use core::mem::ManuallyDrop; 13 use core::ptr::{self, NonNull}; 14 15 /// An intrusive linked list. 16 /// 17 /// Currently, the list is not emptied on drop. It is the caller's 18 /// responsibility to ensure the list is empty before dropping it. 19 pub(crate) struct LinkedList<L, T> { 20 /// Linked list head 21 head: Option<NonNull<T>>, 22 23 /// Linked list tail 24 tail: Option<NonNull<T>>, 25 26 /// Node type marker. 27 _marker: PhantomData<*const L>, 28 } 29 30 unsafe impl<L: Link> Send for LinkedList<L, L::Target> where L::Target: Send {} 31 unsafe impl<L: Link> Sync for LinkedList<L, L::Target> where L::Target: Sync {} 32 33 /// Defines how a type is tracked within a linked list. 34 /// 35 /// In order to support storing a single type within multiple lists, accessing 36 /// the list pointers is decoupled from the entry type. 37 /// 38 /// # Safety 39 /// 40 /// Implementations must guarantee that `Target` types are pinned in memory. In 41 /// other words, when a node is inserted, the value will not be moved as long as 42 /// it is stored in the list. 43 pub(crate) unsafe trait Link { 44 /// Handle to the list entry. 45 /// 46 /// This is usually a pointer-ish type. 47 type Handle; 48 49 /// Node type. 50 type Target; 51 52 /// Convert the handle to a raw pointer without consuming the handle. 53 #[allow(clippy::wrong_self_convention)] as_raw(handle: &Self::Handle) -> NonNull<Self::Target>54 fn as_raw(handle: &Self::Handle) -> NonNull<Self::Target>; 55 56 /// Convert the raw pointer to a handle from_raw(ptr: NonNull<Self::Target>) -> Self::Handle57 unsafe fn from_raw(ptr: NonNull<Self::Target>) -> Self::Handle; 58 59 /// Return the pointers for a node 60 /// 61 /// # Safety 62 /// 63 /// The resulting pointer should have the same tag in the stacked-borrows 64 /// stack as the argument. In particular, the method may not create an 65 /// intermediate reference in the process of creating the resulting raw 66 /// pointer. pointers(target: NonNull<Self::Target>) -> NonNull<Pointers<Self::Target>>67 unsafe fn pointers(target: NonNull<Self::Target>) -> NonNull<Pointers<Self::Target>>; 68 } 69 70 /// Previous / next pointers. 71 pub(crate) struct Pointers<T> { 72 inner: UnsafeCell<PointersInner<T>>, 73 } 74 /// We do not want the compiler to put the `noalias` attribute on mutable 75 /// references to this type, so the type has been made `!Unpin` with a 76 /// `PhantomPinned` field. 77 /// 78 /// Additionally, we never access the `prev` or `next` fields directly, as any 79 /// such access would implicitly involve the creation of a reference to the 80 /// field, which we want to avoid since the fields are not `!Unpin`, and would 81 /// hence be given the `noalias` attribute if we were to do such an access. As 82 /// an alternative to accessing the fields directly, the `Pointers` type 83 /// provides getters and setters for the two fields, and those are implemented 84 /// using `ptr`-specific methods which avoids the creation of intermediate 85 /// references. 86 /// 87 /// See this link for more information: 88 /// <https://github.com/rust-lang/rust/pull/82834> 89 struct PointersInner<T> { 90 /// The previous node in the list. null if there is no previous node. 91 prev: Option<NonNull<T>>, 92 93 /// The next node in the list. null if there is no previous node. 94 next: Option<NonNull<T>>, 95 96 /// This type is !Unpin due to the heuristic from: 97 /// <https://github.com/rust-lang/rust/pull/82834> 98 _pin: PhantomPinned, 99 } 100 101 unsafe impl<T: Send> Send for Pointers<T> {} 102 unsafe impl<T: Sync> Sync for Pointers<T> {} 103 104 // ===== impl LinkedList ===== 105 106 impl<L, T> LinkedList<L, T> { 107 /// Creates an empty linked list. new() -> LinkedList<L, T>108 pub(crate) const fn new() -> LinkedList<L, T> { 109 LinkedList { 110 head: None, 111 tail: None, 112 _marker: PhantomData, 113 } 114 } 115 } 116 117 impl<L: Link> LinkedList<L, L::Target> { 118 /// Adds an element first in the list. push_front(&mut self, val: L::Handle)119 pub(crate) fn push_front(&mut self, val: L::Handle) { 120 // The value should not be dropped, it is being inserted into the list 121 let val = ManuallyDrop::new(val); 122 let ptr = L::as_raw(&val); 123 assert_ne!(self.head, Some(ptr)); 124 unsafe { 125 L::pointers(ptr).as_mut().set_next(self.head); 126 L::pointers(ptr).as_mut().set_prev(None); 127 128 if let Some(head) = self.head { 129 L::pointers(head).as_mut().set_prev(Some(ptr)); 130 } 131 132 self.head = Some(ptr); 133 134 if self.tail.is_none() { 135 self.tail = Some(ptr); 136 } 137 } 138 } 139 140 /// Removes the first element from a list and returns it, or None if it is 141 /// empty. pop_front(&mut self) -> Option<L::Handle>142 pub(crate) fn pop_front(&mut self) -> Option<L::Handle> { 143 unsafe { 144 let head = self.head?; 145 self.head = L::pointers(head).as_ref().get_next(); 146 147 if let Some(new_head) = L::pointers(head).as_ref().get_next() { 148 L::pointers(new_head).as_mut().set_prev(None); 149 } else { 150 self.tail = None; 151 } 152 153 L::pointers(head).as_mut().set_prev(None); 154 L::pointers(head).as_mut().set_next(None); 155 156 Some(L::from_raw(head)) 157 } 158 } 159 160 /// Removes the last element from a list and returns it, or None if it is 161 /// empty. pop_back(&mut self) -> Option<L::Handle>162 pub(crate) fn pop_back(&mut self) -> Option<L::Handle> { 163 unsafe { 164 let last = self.tail?; 165 self.tail = L::pointers(last).as_ref().get_prev(); 166 167 if let Some(prev) = L::pointers(last).as_ref().get_prev() { 168 L::pointers(prev).as_mut().set_next(None); 169 } else { 170 self.head = None; 171 } 172 173 L::pointers(last).as_mut().set_prev(None); 174 L::pointers(last).as_mut().set_next(None); 175 176 Some(L::from_raw(last)) 177 } 178 } 179 180 /// Returns whether the linked list does not contain any node is_empty(&self) -> bool181 pub(crate) fn is_empty(&self) -> bool { 182 if self.head.is_some() { 183 return false; 184 } 185 186 assert!(self.tail.is_none()); 187 true 188 } 189 190 /// Removes the specified node from the list 191 /// 192 /// # Safety 193 /// 194 /// The caller **must** ensure that exactly one of the following is true: 195 /// - `node` is currently contained by `self`, 196 /// - `node` is not contained by any list, 197 /// - `node` is currently contained by some other `GuardedLinkedList` **and** 198 /// the caller has an exclusive access to that list. This condition is 199 /// used by the linked list in `sync::Notify`. remove(&mut self, node: NonNull<L::Target>) -> Option<L::Handle>200 pub(crate) unsafe fn remove(&mut self, node: NonNull<L::Target>) -> Option<L::Handle> { 201 if let Some(prev) = L::pointers(node).as_ref().get_prev() { 202 debug_assert_eq!(L::pointers(prev).as_ref().get_next(), Some(node)); 203 L::pointers(prev) 204 .as_mut() 205 .set_next(L::pointers(node).as_ref().get_next()); 206 } else { 207 if self.head != Some(node) { 208 return None; 209 } 210 211 self.head = L::pointers(node).as_ref().get_next(); 212 } 213 214 if let Some(next) = L::pointers(node).as_ref().get_next() { 215 debug_assert_eq!(L::pointers(next).as_ref().get_prev(), Some(node)); 216 L::pointers(next) 217 .as_mut() 218 .set_prev(L::pointers(node).as_ref().get_prev()); 219 } else { 220 // This might be the last item in the list 221 if self.tail != Some(node) { 222 return None; 223 } 224 225 self.tail = L::pointers(node).as_ref().get_prev(); 226 } 227 228 L::pointers(node).as_mut().set_next(None); 229 L::pointers(node).as_mut().set_prev(None); 230 231 Some(L::from_raw(node)) 232 } 233 } 234 235 impl<L: Link> fmt::Debug for LinkedList<L, L::Target> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result236 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 237 f.debug_struct("LinkedList") 238 .field("head", &self.head) 239 .field("tail", &self.tail) 240 .finish() 241 } 242 } 243 244 #[cfg(any( 245 feature = "fs", 246 feature = "rt", 247 all(unix, feature = "process"), 248 feature = "signal", 249 feature = "sync", 250 ))] 251 impl<L: Link> LinkedList<L, L::Target> { last(&self) -> Option<&L::Target>252 pub(crate) fn last(&self) -> Option<&L::Target> { 253 let tail = self.tail.as_ref()?; 254 unsafe { Some(&*tail.as_ptr()) } 255 } 256 } 257 258 impl<L: Link> Default for LinkedList<L, L::Target> { default() -> Self259 fn default() -> Self { 260 Self::new() 261 } 262 } 263 264 // ===== impl DrainFilter ===== 265 266 cfg_io_driver_impl! { 267 pub(crate) struct DrainFilter<'a, T: Link, F> { 268 list: &'a mut LinkedList<T, T::Target>, 269 filter: F, 270 curr: Option<NonNull<T::Target>>, 271 } 272 273 impl<T: Link> LinkedList<T, T::Target> { 274 pub(crate) fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<'_, T, F> 275 where 276 F: FnMut(&T::Target) -> bool, 277 { 278 let curr = self.head; 279 DrainFilter { 280 curr, 281 filter, 282 list: self, 283 } 284 } 285 } 286 287 impl<'a, T, F> Iterator for DrainFilter<'a, T, F> 288 where 289 T: Link, 290 F: FnMut(&T::Target) -> bool, 291 { 292 type Item = T::Handle; 293 294 fn next(&mut self) -> Option<Self::Item> { 295 while let Some(curr) = self.curr { 296 // safety: the pointer references data contained by the list 297 self.curr = unsafe { T::pointers(curr).as_ref() }.get_next(); 298 299 // safety: the value is still owned by the linked list. 300 if (self.filter)(unsafe { &mut *curr.as_ptr() }) { 301 return unsafe { self.list.remove(curr) }; 302 } 303 } 304 305 None 306 } 307 } 308 } 309 310 cfg_taskdump! { 311 impl<T: Link> LinkedList<T, T::Target> { 312 pub(crate) fn for_each<F>(&mut self, mut f: F) 313 where 314 F: FnMut(&T::Handle), 315 { 316 let mut next = self.head; 317 318 while let Some(curr) = next { 319 unsafe { 320 let handle = ManuallyDrop::new(T::from_raw(curr)); 321 f(&handle); 322 next = T::pointers(curr).as_ref().get_next(); 323 } 324 } 325 } 326 } 327 } 328 329 // ===== impl GuardedLinkedList ===== 330 331 feature! { 332 #![any( 333 feature = "process", 334 feature = "sync", 335 feature = "rt", 336 feature = "signal", 337 )] 338 339 /// An intrusive linked list, but instead of keeping pointers to the head 340 /// and tail nodes, it uses a special guard node linked with those nodes. 341 /// It means that the list is circular and every pointer of a node from 342 /// the list is not `None`, including pointers from the guard node. 343 /// 344 /// If a list is empty, then both pointers of the guard node are pointing 345 /// at the guard node itself. 346 pub(crate) struct GuardedLinkedList<L, T> { 347 /// Pointer to the guard node. 348 guard: NonNull<T>, 349 350 /// Node type marker. 351 _marker: PhantomData<*const L>, 352 } 353 354 impl<L: Link> LinkedList<L, L::Target> { 355 /// Turns a linked list into the guarded version by linking the guard node 356 /// with the head and tail nodes. Like with other nodes, you should guarantee 357 /// that the guard node is pinned in memory. 358 pub(crate) fn into_guarded(self, guard_handle: L::Handle) -> GuardedLinkedList<L, L::Target> { 359 // `guard_handle` is a NonNull pointer, we don't have to care about dropping it. 360 let guard = L::as_raw(&guard_handle); 361 362 unsafe { 363 if let Some(head) = self.head { 364 debug_assert!(L::pointers(head).as_ref().get_prev().is_none()); 365 L::pointers(head).as_mut().set_prev(Some(guard)); 366 L::pointers(guard).as_mut().set_next(Some(head)); 367 368 // The list is not empty, so the tail cannot be `None`. 369 let tail = self.tail.unwrap(); 370 debug_assert!(L::pointers(tail).as_ref().get_next().is_none()); 371 L::pointers(tail).as_mut().set_next(Some(guard)); 372 L::pointers(guard).as_mut().set_prev(Some(tail)); 373 } else { 374 // The list is empty. 375 L::pointers(guard).as_mut().set_prev(Some(guard)); 376 L::pointers(guard).as_mut().set_next(Some(guard)); 377 } 378 } 379 380 GuardedLinkedList { guard, _marker: PhantomData } 381 } 382 } 383 384 impl<L: Link> GuardedLinkedList<L, L::Target> { 385 fn tail(&self) -> Option<NonNull<L::Target>> { 386 let tail_ptr = unsafe { 387 L::pointers(self.guard).as_ref().get_prev().unwrap() 388 }; 389 390 // Compare the tail pointer with the address of the guard node itself. 391 // If the guard points at itself, then there are no other nodes and 392 // the list is considered empty. 393 if tail_ptr != self.guard { 394 Some(tail_ptr) 395 } else { 396 None 397 } 398 } 399 400 /// Removes the last element from a list and returns it, or None if it is 401 /// empty. 402 pub(crate) fn pop_back(&mut self) -> Option<L::Handle> { 403 unsafe { 404 let last = self.tail()?; 405 let before_last = L::pointers(last).as_ref().get_prev().unwrap(); 406 407 L::pointers(self.guard).as_mut().set_prev(Some(before_last)); 408 L::pointers(before_last).as_mut().set_next(Some(self.guard)); 409 410 L::pointers(last).as_mut().set_prev(None); 411 L::pointers(last).as_mut().set_next(None); 412 413 Some(L::from_raw(last)) 414 } 415 } 416 } 417 } 418 419 // ===== impl Pointers ===== 420 421 impl<T> Pointers<T> { 422 /// Create a new set of empty pointers new() -> Pointers<T>423 pub(crate) fn new() -> Pointers<T> { 424 Pointers { 425 inner: UnsafeCell::new(PointersInner { 426 prev: None, 427 next: None, 428 _pin: PhantomPinned, 429 }), 430 } 431 } 432 get_prev(&self) -> Option<NonNull<T>>433 pub(crate) fn get_prev(&self) -> Option<NonNull<T>> { 434 // SAFETY: Field is accessed immutably through a reference. 435 unsafe { ptr::addr_of!((*self.inner.get()).prev).read() } 436 } get_next(&self) -> Option<NonNull<T>>437 pub(crate) fn get_next(&self) -> Option<NonNull<T>> { 438 // SAFETY: Field is accessed immutably through a reference. 439 unsafe { ptr::addr_of!((*self.inner.get()).next).read() } 440 } 441 set_prev(&mut self, value: Option<NonNull<T>>)442 fn set_prev(&mut self, value: Option<NonNull<T>>) { 443 // SAFETY: Field is accessed mutably through a mutable reference. 444 unsafe { 445 ptr::addr_of_mut!((*self.inner.get()).prev).write(value); 446 } 447 } set_next(&mut self, value: Option<NonNull<T>>)448 fn set_next(&mut self, value: Option<NonNull<T>>) { 449 // SAFETY: Field is accessed mutably through a mutable reference. 450 unsafe { 451 ptr::addr_of_mut!((*self.inner.get()).next).write(value); 452 } 453 } 454 } 455 456 impl<T> fmt::Debug for Pointers<T> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result457 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 458 let prev = self.get_prev(); 459 let next = self.get_next(); 460 f.debug_struct("Pointers") 461 .field("prev", &prev) 462 .field("next", &next) 463 .finish() 464 } 465 } 466 467 #[cfg(any(test, fuzzing))] 468 #[cfg(not(loom))] 469 pub(crate) mod tests { 470 use super::*; 471 472 use std::pin::Pin; 473 474 #[derive(Debug)] 475 #[repr(C)] 476 struct Entry { 477 pointers: Pointers<Entry>, 478 val: i32, 479 } 480 481 unsafe impl<'a> Link for &'a Entry { 482 type Handle = Pin<&'a Entry>; 483 type Target = Entry; 484 as_raw(handle: &Pin<&'_ Entry>) -> NonNull<Entry>485 fn as_raw(handle: &Pin<&'_ Entry>) -> NonNull<Entry> { 486 NonNull::from(handle.get_ref()) 487 } 488 from_raw(ptr: NonNull<Entry>) -> Pin<&'a Entry>489 unsafe fn from_raw(ptr: NonNull<Entry>) -> Pin<&'a Entry> { 490 Pin::new_unchecked(&*ptr.as_ptr()) 491 } 492 pointers(target: NonNull<Entry>) -> NonNull<Pointers<Entry>>493 unsafe fn pointers(target: NonNull<Entry>) -> NonNull<Pointers<Entry>> { 494 target.cast() 495 } 496 } 497 entry(val: i32) -> Pin<Box<Entry>>498 fn entry(val: i32) -> Pin<Box<Entry>> { 499 Box::pin(Entry { 500 pointers: Pointers::new(), 501 val, 502 }) 503 } 504 ptr(r: &Pin<Box<Entry>>) -> NonNull<Entry>505 fn ptr(r: &Pin<Box<Entry>>) -> NonNull<Entry> { 506 r.as_ref().get_ref().into() 507 } 508 collect_list(list: &mut LinkedList<&'_ Entry, <&'_ Entry as Link>::Target>) -> Vec<i32>509 fn collect_list(list: &mut LinkedList<&'_ Entry, <&'_ Entry as Link>::Target>) -> Vec<i32> { 510 let mut ret = vec![]; 511 512 while let Some(entry) = list.pop_back() { 513 ret.push(entry.val); 514 } 515 516 ret 517 } 518 push_all<'a>( list: &mut LinkedList<&'a Entry, <&'_ Entry as Link>::Target>, entries: &[Pin<&'a Entry>], )519 fn push_all<'a>( 520 list: &mut LinkedList<&'a Entry, <&'_ Entry as Link>::Target>, 521 entries: &[Pin<&'a Entry>], 522 ) { 523 for entry in entries.iter() { 524 list.push_front(*entry); 525 } 526 } 527 528 #[cfg(test)] 529 macro_rules! assert_clean { 530 ($e:ident) => {{ 531 assert!($e.pointers.get_next().is_none()); 532 assert!($e.pointers.get_prev().is_none()); 533 }}; 534 } 535 536 #[cfg(test)] 537 macro_rules! assert_ptr_eq { 538 ($a:expr, $b:expr) => {{ 539 // Deal with mapping a Pin<&mut T> -> Option<NonNull<T>> 540 assert_eq!(Some($a.as_ref().get_ref().into()), $b) 541 }}; 542 } 543 544 #[test] const_new()545 fn const_new() { 546 const _: LinkedList<&Entry, <&Entry as Link>::Target> = LinkedList::new(); 547 } 548 549 #[test] push_and_drain()550 fn push_and_drain() { 551 let a = entry(5); 552 let b = entry(7); 553 let c = entry(31); 554 555 let mut list = LinkedList::new(); 556 assert!(list.is_empty()); 557 558 list.push_front(a.as_ref()); 559 assert!(!list.is_empty()); 560 list.push_front(b.as_ref()); 561 list.push_front(c.as_ref()); 562 563 let items: Vec<i32> = collect_list(&mut list); 564 assert_eq!([5, 7, 31].to_vec(), items); 565 566 assert!(list.is_empty()); 567 } 568 569 #[test] push_pop_push_pop()570 fn push_pop_push_pop() { 571 let a = entry(5); 572 let b = entry(7); 573 574 let mut list = LinkedList::<&Entry, <&Entry as Link>::Target>::new(); 575 576 list.push_front(a.as_ref()); 577 578 let entry = list.pop_back().unwrap(); 579 assert_eq!(5, entry.val); 580 assert!(list.is_empty()); 581 582 list.push_front(b.as_ref()); 583 584 let entry = list.pop_back().unwrap(); 585 assert_eq!(7, entry.val); 586 587 assert!(list.is_empty()); 588 assert!(list.pop_back().is_none()); 589 } 590 591 #[test] remove_by_address()592 fn remove_by_address() { 593 let a = entry(5); 594 let b = entry(7); 595 let c = entry(31); 596 597 unsafe { 598 // Remove first 599 let mut list = LinkedList::new(); 600 601 push_all(&mut list, &[c.as_ref(), b.as_ref(), a.as_ref()]); 602 assert!(list.remove(ptr(&a)).is_some()); 603 assert_clean!(a); 604 // `a` should be no longer there and can't be removed twice 605 assert!(list.remove(ptr(&a)).is_none()); 606 assert!(!list.is_empty()); 607 608 assert!(list.remove(ptr(&b)).is_some()); 609 assert_clean!(b); 610 // `b` should be no longer there and can't be removed twice 611 assert!(list.remove(ptr(&b)).is_none()); 612 assert!(!list.is_empty()); 613 614 assert!(list.remove(ptr(&c)).is_some()); 615 assert_clean!(c); 616 // `b` should be no longer there and can't be removed twice 617 assert!(list.remove(ptr(&c)).is_none()); 618 assert!(list.is_empty()); 619 } 620 621 unsafe { 622 // Remove middle 623 let mut list = LinkedList::new(); 624 625 push_all(&mut list, &[c.as_ref(), b.as_ref(), a.as_ref()]); 626 627 assert!(list.remove(ptr(&a)).is_some()); 628 assert_clean!(a); 629 630 assert_ptr_eq!(b, list.head); 631 assert_ptr_eq!(c, b.pointers.get_next()); 632 assert_ptr_eq!(b, c.pointers.get_prev()); 633 634 let items = collect_list(&mut list); 635 assert_eq!([31, 7].to_vec(), items); 636 } 637 638 unsafe { 639 // Remove middle 640 let mut list = LinkedList::new(); 641 642 push_all(&mut list, &[c.as_ref(), b.as_ref(), a.as_ref()]); 643 644 assert!(list.remove(ptr(&b)).is_some()); 645 assert_clean!(b); 646 647 assert_ptr_eq!(c, a.pointers.get_next()); 648 assert_ptr_eq!(a, c.pointers.get_prev()); 649 650 let items = collect_list(&mut list); 651 assert_eq!([31, 5].to_vec(), items); 652 } 653 654 unsafe { 655 // Remove last 656 // Remove middle 657 let mut list = LinkedList::new(); 658 659 push_all(&mut list, &[c.as_ref(), b.as_ref(), a.as_ref()]); 660 661 assert!(list.remove(ptr(&c)).is_some()); 662 assert_clean!(c); 663 664 assert!(b.pointers.get_next().is_none()); 665 assert_ptr_eq!(b, list.tail); 666 667 let items = collect_list(&mut list); 668 assert_eq!([7, 5].to_vec(), items); 669 } 670 671 unsafe { 672 // Remove first of two 673 let mut list = LinkedList::new(); 674 675 push_all(&mut list, &[b.as_ref(), a.as_ref()]); 676 677 assert!(list.remove(ptr(&a)).is_some()); 678 679 assert_clean!(a); 680 681 // a should be no longer there and can't be removed twice 682 assert!(list.remove(ptr(&a)).is_none()); 683 684 assert_ptr_eq!(b, list.head); 685 assert_ptr_eq!(b, list.tail); 686 687 assert!(b.pointers.get_next().is_none()); 688 assert!(b.pointers.get_prev().is_none()); 689 690 let items = collect_list(&mut list); 691 assert_eq!([7].to_vec(), items); 692 } 693 694 unsafe { 695 // Remove last of two 696 let mut list = LinkedList::new(); 697 698 push_all(&mut list, &[b.as_ref(), a.as_ref()]); 699 700 assert!(list.remove(ptr(&b)).is_some()); 701 702 assert_clean!(b); 703 704 assert_ptr_eq!(a, list.head); 705 assert_ptr_eq!(a, list.tail); 706 707 assert!(a.pointers.get_next().is_none()); 708 assert!(a.pointers.get_prev().is_none()); 709 710 let items = collect_list(&mut list); 711 assert_eq!([5].to_vec(), items); 712 } 713 714 unsafe { 715 // Remove last item 716 let mut list = LinkedList::new(); 717 718 push_all(&mut list, &[a.as_ref()]); 719 720 assert!(list.remove(ptr(&a)).is_some()); 721 assert_clean!(a); 722 723 assert!(list.head.is_none()); 724 assert!(list.tail.is_none()); 725 let items = collect_list(&mut list); 726 assert!(items.is_empty()); 727 } 728 729 unsafe { 730 // Remove missing 731 let mut list = LinkedList::<&Entry, <&Entry as Link>::Target>::new(); 732 733 list.push_front(b.as_ref()); 734 list.push_front(a.as_ref()); 735 736 assert!(list.remove(ptr(&c)).is_none()); 737 } 738 } 739 740 /// This is a fuzz test. You run it by entering `cargo fuzz run fuzz_linked_list` in CLI in `/tokio/` module. 741 #[cfg(fuzzing)] fuzz_linked_list(ops: &[u8])742 pub fn fuzz_linked_list(ops: &[u8]) { 743 enum Op { 744 Push, 745 Pop, 746 Remove(usize), 747 } 748 use std::collections::VecDeque; 749 750 let ops = ops 751 .iter() 752 .map(|i| match i % 3u8 { 753 0 => Op::Push, 754 1 => Op::Pop, 755 2 => Op::Remove((i / 3u8) as usize), 756 _ => unreachable!(), 757 }) 758 .collect::<Vec<_>>(); 759 760 let mut ll = LinkedList::<&Entry, <&Entry as Link>::Target>::new(); 761 let mut reference = VecDeque::new(); 762 763 let entries: Vec<_> = (0..ops.len()).map(|i| entry(i as i32)).collect(); 764 765 for (i, op) in ops.iter().enumerate() { 766 match op { 767 Op::Push => { 768 reference.push_front(i as i32); 769 assert_eq!(entries[i].val, i as i32); 770 771 ll.push_front(entries[i].as_ref()); 772 } 773 Op::Pop => { 774 if reference.is_empty() { 775 assert!(ll.is_empty()); 776 continue; 777 } 778 779 let v = reference.pop_back(); 780 assert_eq!(v, ll.pop_back().map(|v| v.val)); 781 } 782 Op::Remove(n) => { 783 if reference.is_empty() { 784 assert!(ll.is_empty()); 785 continue; 786 } 787 788 let idx = n % reference.len(); 789 let expect = reference.remove(idx).unwrap(); 790 791 unsafe { 792 let entry = ll.remove(ptr(&entries[expect as usize])).unwrap(); 793 assert_eq!(expect, entry.val); 794 } 795 } 796 } 797 } 798 } 799 } 800