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. 82 /// As 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 raw pointer casts and offsets, which is valid since the struct is 85 /// #[repr(C)]. 86 /// 87 /// See this link for more information: 88 /// <https://github.com/rust-lang/rust/pull/82834> 89 #[repr(C)] 90 struct PointersInner<T> { 91 /// The previous node in the list. null if there is no previous node. 92 /// 93 /// This field is accessed through pointer manipulation, so it is not dead code. 94 #[allow(dead_code)] 95 prev: Option<NonNull<T>>, 96 97 /// The next node in the list. null if there is no previous node. 98 /// 99 /// This field is accessed through pointer manipulation, so it is not dead code. 100 #[allow(dead_code)] 101 next: Option<NonNull<T>>, 102 103 /// This type is !Unpin due to the heuristic from: 104 /// <https://github.com/rust-lang/rust/pull/82834> 105 _pin: PhantomPinned, 106 } 107 108 unsafe impl<T: Send> Send for Pointers<T> {} 109 unsafe impl<T: Sync> Sync for Pointers<T> {} 110 111 // ===== impl LinkedList ===== 112 113 impl<L, T> LinkedList<L, T> { 114 /// Creates an empty linked list. new() -> LinkedList<L, T>115 pub(crate) const fn new() -> LinkedList<L, T> { 116 LinkedList { 117 head: None, 118 tail: None, 119 _marker: PhantomData, 120 } 121 } 122 } 123 124 impl<L: Link> LinkedList<L, L::Target> { 125 /// Adds an element first in the list. push_front(&mut self, val: L::Handle)126 pub(crate) fn push_front(&mut self, val: L::Handle) { 127 // The value should not be dropped, it is being inserted into the list 128 let val = ManuallyDrop::new(val); 129 let ptr = L::as_raw(&val); 130 assert_ne!(self.head, Some(ptr)); 131 unsafe { 132 L::pointers(ptr).as_mut().set_next(self.head); 133 L::pointers(ptr).as_mut().set_prev(None); 134 135 if let Some(head) = self.head { 136 L::pointers(head).as_mut().set_prev(Some(ptr)); 137 } 138 139 self.head = Some(ptr); 140 141 if self.tail.is_none() { 142 self.tail = Some(ptr); 143 } 144 } 145 } 146 147 /// Removes the last element from a list and returns it, or None if it is 148 /// empty. pop_back(&mut self) -> Option<L::Handle>149 pub(crate) fn pop_back(&mut self) -> Option<L::Handle> { 150 unsafe { 151 let last = self.tail?; 152 self.tail = L::pointers(last).as_ref().get_prev(); 153 154 if let Some(prev) = L::pointers(last).as_ref().get_prev() { 155 L::pointers(prev).as_mut().set_next(None); 156 } else { 157 self.head = None 158 } 159 160 L::pointers(last).as_mut().set_prev(None); 161 L::pointers(last).as_mut().set_next(None); 162 163 Some(L::from_raw(last)) 164 } 165 } 166 167 /// Returns whether the linked list does not contain any node is_empty(&self) -> bool168 pub(crate) fn is_empty(&self) -> bool { 169 if self.head.is_some() { 170 return false; 171 } 172 173 assert!(self.tail.is_none()); 174 true 175 } 176 177 /// Removes the specified node from the list 178 /// 179 /// # Safety 180 /// 181 /// The caller **must** ensure that exactly one of the following is true: 182 /// - `node` is currently contained by `self`, 183 /// - `node` is not contained by any list, 184 /// - `node` is currently contained by some other `GuardedLinkedList` **and** 185 /// the caller has an exclusive access to that list. This condition is 186 /// used by the linked list in `sync::Notify`. remove(&mut self, node: NonNull<L::Target>) -> Option<L::Handle>187 pub(crate) unsafe fn remove(&mut self, node: NonNull<L::Target>) -> Option<L::Handle> { 188 if let Some(prev) = L::pointers(node).as_ref().get_prev() { 189 debug_assert_eq!(L::pointers(prev).as_ref().get_next(), Some(node)); 190 L::pointers(prev) 191 .as_mut() 192 .set_next(L::pointers(node).as_ref().get_next()); 193 } else { 194 if self.head != Some(node) { 195 return None; 196 } 197 198 self.head = L::pointers(node).as_ref().get_next(); 199 } 200 201 if let Some(next) = L::pointers(node).as_ref().get_next() { 202 debug_assert_eq!(L::pointers(next).as_ref().get_prev(), Some(node)); 203 L::pointers(next) 204 .as_mut() 205 .set_prev(L::pointers(node).as_ref().get_prev()); 206 } else { 207 // This might be the last item in the list 208 if self.tail != Some(node) { 209 return None; 210 } 211 212 self.tail = L::pointers(node).as_ref().get_prev(); 213 } 214 215 L::pointers(node).as_mut().set_next(None); 216 L::pointers(node).as_mut().set_prev(None); 217 218 Some(L::from_raw(node)) 219 } 220 } 221 222 impl<L: Link> fmt::Debug for LinkedList<L, L::Target> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result223 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 224 f.debug_struct("LinkedList") 225 .field("head", &self.head) 226 .field("tail", &self.tail) 227 .finish() 228 } 229 } 230 231 // ===== impl CountedLinkedList ==== 232 233 // Delegates operations to the base LinkedList implementation, and adds a counter to the elements 234 // in the list. 235 pub(crate) struct CountedLinkedList<L: Link, T> { 236 list: LinkedList<L, T>, 237 count: usize, 238 } 239 240 impl<L: Link> CountedLinkedList<L, L::Target> { new() -> CountedLinkedList<L, L::Target>241 pub(crate) fn new() -> CountedLinkedList<L, L::Target> { 242 CountedLinkedList { 243 list: LinkedList::new(), 244 count: 0, 245 } 246 } 247 push_front(&mut self, val: L::Handle)248 pub(crate) fn push_front(&mut self, val: L::Handle) { 249 self.list.push_front(val); 250 self.count += 1; 251 } 252 pop_back(&mut self) -> Option<L::Handle>253 pub(crate) fn pop_back(&mut self) -> Option<L::Handle> { 254 let val = self.list.pop_back(); 255 if val.is_some() { 256 self.count -= 1; 257 } 258 val 259 } 260 is_empty(&self) -> bool261 pub(crate) fn is_empty(&self) -> bool { 262 self.list.is_empty() 263 } 264 remove(&mut self, node: NonNull<L::Target>) -> Option<L::Handle>265 pub(crate) unsafe fn remove(&mut self, node: NonNull<L::Target>) -> Option<L::Handle> { 266 let val = self.list.remove(node); 267 if val.is_some() { 268 self.count -= 1; 269 } 270 val 271 } 272 count(&self) -> usize273 pub(crate) fn count(&self) -> usize { 274 self.count 275 } 276 } 277 278 #[cfg(any( 279 feature = "fs", 280 feature = "rt", 281 all(unix, feature = "process"), 282 feature = "signal", 283 feature = "sync", 284 ))] 285 impl<L: Link> LinkedList<L, L::Target> { last(&self) -> Option<&L::Target>286 pub(crate) fn last(&self) -> Option<&L::Target> { 287 let tail = self.tail.as_ref()?; 288 unsafe { Some(&*tail.as_ptr()) } 289 } 290 } 291 292 impl<L: Link> Default for LinkedList<L, L::Target> { default() -> Self293 fn default() -> Self { 294 Self::new() 295 } 296 } 297 298 // ===== impl DrainFilter ===== 299 300 cfg_io_driver_impl! { 301 pub(crate) struct DrainFilter<'a, T: Link, F> { 302 list: &'a mut LinkedList<T, T::Target>, 303 filter: F, 304 curr: Option<NonNull<T::Target>>, 305 } 306 307 impl<T: Link> LinkedList<T, T::Target> { 308 pub(crate) fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<'_, T, F> 309 where 310 F: FnMut(&T::Target) -> bool, 311 { 312 let curr = self.head; 313 DrainFilter { 314 curr, 315 filter, 316 list: self, 317 } 318 } 319 } 320 321 impl<'a, T, F> Iterator for DrainFilter<'a, T, F> 322 where 323 T: Link, 324 F: FnMut(&T::Target) -> bool, 325 { 326 type Item = T::Handle; 327 328 fn next(&mut self) -> Option<Self::Item> { 329 while let Some(curr) = self.curr { 330 // safety: the pointer references data contained by the list 331 self.curr = unsafe { T::pointers(curr).as_ref() }.get_next(); 332 333 // safety: the value is still owned by the linked list. 334 if (self.filter)(unsafe { &mut *curr.as_ptr() }) { 335 return unsafe { self.list.remove(curr) }; 336 } 337 } 338 339 None 340 } 341 } 342 } 343 344 cfg_taskdump! { 345 impl<T: Link> CountedLinkedList<T, T::Target> { 346 pub(crate) fn for_each<F>(&mut self, f: F) 347 where 348 F: FnMut(&T::Handle), 349 { 350 self.list.for_each(f) 351 } 352 } 353 354 impl<T: Link> LinkedList<T, T::Target> { 355 pub(crate) fn for_each<F>(&mut self, mut f: F) 356 where 357 F: FnMut(&T::Handle), 358 { 359 use std::mem::ManuallyDrop; 360 361 let mut next = self.head; 362 363 while let Some(curr) = next { 364 unsafe { 365 let handle = ManuallyDrop::new(T::from_raw(curr)); 366 f(&handle); 367 next = T::pointers(curr).as_ref().get_next(); 368 } 369 } 370 } 371 } 372 } 373 374 // ===== impl GuardedLinkedList ===== 375 376 feature! { 377 #![any( 378 feature = "process", 379 feature = "sync", 380 feature = "rt", 381 feature = "signal", 382 )] 383 384 /// An intrusive linked list, but instead of keeping pointers to the head 385 /// and tail nodes, it uses a special guard node linked with those nodes. 386 /// It means that the list is circular and every pointer of a node from 387 /// the list is not `None`, including pointers from the guard node. 388 /// 389 /// If a list is empty, then both pointers of the guard node are pointing 390 /// at the guard node itself. 391 pub(crate) struct GuardedLinkedList<L, T> { 392 /// Pointer to the guard node. 393 guard: NonNull<T>, 394 395 /// Node type marker. 396 _marker: PhantomData<*const L>, 397 } 398 399 impl<U, L: Link<Handle = NonNull<U>>> LinkedList<L, L::Target> { 400 /// Turns a linked list into the guarded version by linking the guard node 401 /// with the head and tail nodes. Like with other nodes, you should guarantee 402 /// that the guard node is pinned in memory. 403 pub(crate) fn into_guarded(self, guard_handle: L::Handle) -> GuardedLinkedList<L, L::Target> { 404 // `guard_handle` is a NonNull pointer, we don't have to care about dropping it. 405 let guard = L::as_raw(&guard_handle); 406 407 unsafe { 408 if let Some(head) = self.head { 409 debug_assert!(L::pointers(head).as_ref().get_prev().is_none()); 410 L::pointers(head).as_mut().set_prev(Some(guard)); 411 L::pointers(guard).as_mut().set_next(Some(head)); 412 413 // The list is not empty, so the tail cannot be `None`. 414 let tail = self.tail.unwrap(); 415 debug_assert!(L::pointers(tail).as_ref().get_next().is_none()); 416 L::pointers(tail).as_mut().set_next(Some(guard)); 417 L::pointers(guard).as_mut().set_prev(Some(tail)); 418 } else { 419 // The list is empty. 420 L::pointers(guard).as_mut().set_prev(Some(guard)); 421 L::pointers(guard).as_mut().set_next(Some(guard)); 422 } 423 } 424 425 GuardedLinkedList { guard, _marker: PhantomData } 426 } 427 } 428 429 impl<L: Link> GuardedLinkedList<L, L::Target> { 430 fn tail(&self) -> Option<NonNull<L::Target>> { 431 let tail_ptr = unsafe { 432 L::pointers(self.guard).as_ref().get_prev().unwrap() 433 }; 434 435 // Compare the tail pointer with the address of the guard node itself. 436 // If the guard points at itself, then there are no other nodes and 437 // the list is considered empty. 438 if tail_ptr != self.guard { 439 Some(tail_ptr) 440 } else { 441 None 442 } 443 } 444 445 /// Removes the last element from a list and returns it, or None if it is 446 /// empty. 447 pub(crate) fn pop_back(&mut self) -> Option<L::Handle> { 448 unsafe { 449 let last = self.tail()?; 450 let before_last = L::pointers(last).as_ref().get_prev().unwrap(); 451 452 L::pointers(self.guard).as_mut().set_prev(Some(before_last)); 453 L::pointers(before_last).as_mut().set_next(Some(self.guard)); 454 455 L::pointers(last).as_mut().set_prev(None); 456 L::pointers(last).as_mut().set_next(None); 457 458 Some(L::from_raw(last)) 459 } 460 } 461 } 462 } 463 464 // ===== impl Pointers ===== 465 466 impl<T> Pointers<T> { 467 /// Create a new set of empty pointers new() -> Pointers<T>468 pub(crate) fn new() -> Pointers<T> { 469 Pointers { 470 inner: UnsafeCell::new(PointersInner { 471 prev: None, 472 next: None, 473 _pin: PhantomPinned, 474 }), 475 } 476 } 477 get_prev(&self) -> Option<NonNull<T>>478 pub(crate) fn get_prev(&self) -> Option<NonNull<T>> { 479 // SAFETY: prev is the first field in PointersInner, which is #[repr(C)]. 480 unsafe { 481 let inner = self.inner.get(); 482 let prev = inner as *const Option<NonNull<T>>; 483 ptr::read(prev) 484 } 485 } get_next(&self) -> Option<NonNull<T>>486 pub(crate) fn get_next(&self) -> Option<NonNull<T>> { 487 // SAFETY: next is the second field in PointersInner, which is #[repr(C)]. 488 unsafe { 489 let inner = self.inner.get(); 490 let prev = inner as *const Option<NonNull<T>>; 491 let next = prev.add(1); 492 ptr::read(next) 493 } 494 } 495 set_prev(&mut self, value: Option<NonNull<T>>)496 fn set_prev(&mut self, value: Option<NonNull<T>>) { 497 // SAFETY: prev is the first field in PointersInner, which is #[repr(C)]. 498 unsafe { 499 let inner = self.inner.get(); 500 let prev = inner as *mut Option<NonNull<T>>; 501 ptr::write(prev, value); 502 } 503 } set_next(&mut self, value: Option<NonNull<T>>)504 fn set_next(&mut self, value: Option<NonNull<T>>) { 505 // SAFETY: next is the second field in PointersInner, which is #[repr(C)]. 506 unsafe { 507 let inner = self.inner.get(); 508 let prev = inner as *mut Option<NonNull<T>>; 509 let next = prev.add(1); 510 ptr::write(next, value); 511 } 512 } 513 } 514 515 impl<T> fmt::Debug for Pointers<T> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result516 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 517 let prev = self.get_prev(); 518 let next = self.get_next(); 519 f.debug_struct("Pointers") 520 .field("prev", &prev) 521 .field("next", &next) 522 .finish() 523 } 524 } 525 526 #[cfg(any(test, fuzzing))] 527 #[cfg(not(loom))] 528 pub(crate) mod tests { 529 use super::*; 530 531 use std::pin::Pin; 532 533 #[derive(Debug)] 534 #[repr(C)] 535 struct Entry { 536 pointers: Pointers<Entry>, 537 val: i32, 538 } 539 540 unsafe impl<'a> Link for &'a Entry { 541 type Handle = Pin<&'a Entry>; 542 type Target = Entry; 543 as_raw(handle: &Pin<&'_ Entry>) -> NonNull<Entry>544 fn as_raw(handle: &Pin<&'_ Entry>) -> NonNull<Entry> { 545 NonNull::from(handle.get_ref()) 546 } 547 from_raw(ptr: NonNull<Entry>) -> Pin<&'a Entry>548 unsafe fn from_raw(ptr: NonNull<Entry>) -> Pin<&'a Entry> { 549 Pin::new_unchecked(&*ptr.as_ptr()) 550 } 551 pointers(target: NonNull<Entry>) -> NonNull<Pointers<Entry>>552 unsafe fn pointers(target: NonNull<Entry>) -> NonNull<Pointers<Entry>> { 553 target.cast() 554 } 555 } 556 entry(val: i32) -> Pin<Box<Entry>>557 fn entry(val: i32) -> Pin<Box<Entry>> { 558 Box::pin(Entry { 559 pointers: Pointers::new(), 560 val, 561 }) 562 } 563 ptr(r: &Pin<Box<Entry>>) -> NonNull<Entry>564 fn ptr(r: &Pin<Box<Entry>>) -> NonNull<Entry> { 565 r.as_ref().get_ref().into() 566 } 567 collect_list(list: &mut LinkedList<&'_ Entry, <&'_ Entry as Link>::Target>) -> Vec<i32>568 fn collect_list(list: &mut LinkedList<&'_ Entry, <&'_ Entry as Link>::Target>) -> Vec<i32> { 569 let mut ret = vec![]; 570 571 while let Some(entry) = list.pop_back() { 572 ret.push(entry.val); 573 } 574 575 ret 576 } 577 push_all<'a>( list: &mut LinkedList<&'a Entry, <&'_ Entry as Link>::Target>, entries: &[Pin<&'a Entry>], )578 fn push_all<'a>( 579 list: &mut LinkedList<&'a Entry, <&'_ Entry as Link>::Target>, 580 entries: &[Pin<&'a Entry>], 581 ) { 582 for entry in entries.iter() { 583 list.push_front(*entry); 584 } 585 } 586 587 #[cfg(test)] 588 macro_rules! assert_clean { 589 ($e:ident) => {{ 590 assert!($e.pointers.get_next().is_none()); 591 assert!($e.pointers.get_prev().is_none()); 592 }}; 593 } 594 595 #[cfg(test)] 596 macro_rules! assert_ptr_eq { 597 ($a:expr, $b:expr) => {{ 598 // Deal with mapping a Pin<&mut T> -> Option<NonNull<T>> 599 assert_eq!(Some($a.as_ref().get_ref().into()), $b) 600 }}; 601 } 602 603 #[test] const_new()604 fn const_new() { 605 const _: LinkedList<&Entry, <&Entry as Link>::Target> = LinkedList::new(); 606 } 607 608 #[test] push_and_drain()609 fn push_and_drain() { 610 let a = entry(5); 611 let b = entry(7); 612 let c = entry(31); 613 614 let mut list = LinkedList::new(); 615 assert!(list.is_empty()); 616 617 list.push_front(a.as_ref()); 618 assert!(!list.is_empty()); 619 list.push_front(b.as_ref()); 620 list.push_front(c.as_ref()); 621 622 let items: Vec<i32> = collect_list(&mut list); 623 assert_eq!([5, 7, 31].to_vec(), items); 624 625 assert!(list.is_empty()); 626 } 627 628 #[test] push_pop_push_pop()629 fn push_pop_push_pop() { 630 let a = entry(5); 631 let b = entry(7); 632 633 let mut list = LinkedList::<&Entry, <&Entry as Link>::Target>::new(); 634 635 list.push_front(a.as_ref()); 636 637 let entry = list.pop_back().unwrap(); 638 assert_eq!(5, entry.val); 639 assert!(list.is_empty()); 640 641 list.push_front(b.as_ref()); 642 643 let entry = list.pop_back().unwrap(); 644 assert_eq!(7, entry.val); 645 646 assert!(list.is_empty()); 647 assert!(list.pop_back().is_none()); 648 } 649 650 #[test] remove_by_address()651 fn remove_by_address() { 652 let a = entry(5); 653 let b = entry(7); 654 let c = entry(31); 655 656 unsafe { 657 // Remove first 658 let mut list = LinkedList::new(); 659 660 push_all(&mut list, &[c.as_ref(), b.as_ref(), a.as_ref()]); 661 assert!(list.remove(ptr(&a)).is_some()); 662 assert_clean!(a); 663 // `a` should be no longer there and can't be removed twice 664 assert!(list.remove(ptr(&a)).is_none()); 665 assert!(!list.is_empty()); 666 667 assert!(list.remove(ptr(&b)).is_some()); 668 assert_clean!(b); 669 // `b` should be no longer there and can't be removed twice 670 assert!(list.remove(ptr(&b)).is_none()); 671 assert!(!list.is_empty()); 672 673 assert!(list.remove(ptr(&c)).is_some()); 674 assert_clean!(c); 675 // `b` should be no longer there and can't be removed twice 676 assert!(list.remove(ptr(&c)).is_none()); 677 assert!(list.is_empty()); 678 } 679 680 unsafe { 681 // Remove middle 682 let mut list = LinkedList::new(); 683 684 push_all(&mut list, &[c.as_ref(), b.as_ref(), a.as_ref()]); 685 686 assert!(list.remove(ptr(&a)).is_some()); 687 assert_clean!(a); 688 689 assert_ptr_eq!(b, list.head); 690 assert_ptr_eq!(c, b.pointers.get_next()); 691 assert_ptr_eq!(b, c.pointers.get_prev()); 692 693 let items = collect_list(&mut list); 694 assert_eq!([31, 7].to_vec(), items); 695 } 696 697 unsafe { 698 // Remove middle 699 let mut list = LinkedList::new(); 700 701 push_all(&mut list, &[c.as_ref(), b.as_ref(), a.as_ref()]); 702 703 assert!(list.remove(ptr(&b)).is_some()); 704 assert_clean!(b); 705 706 assert_ptr_eq!(c, a.pointers.get_next()); 707 assert_ptr_eq!(a, c.pointers.get_prev()); 708 709 let items = collect_list(&mut list); 710 assert_eq!([31, 5].to_vec(), items); 711 } 712 713 unsafe { 714 // Remove last 715 // Remove middle 716 let mut list = LinkedList::new(); 717 718 push_all(&mut list, &[c.as_ref(), b.as_ref(), a.as_ref()]); 719 720 assert!(list.remove(ptr(&c)).is_some()); 721 assert_clean!(c); 722 723 assert!(b.pointers.get_next().is_none()); 724 assert_ptr_eq!(b, list.tail); 725 726 let items = collect_list(&mut list); 727 assert_eq!([7, 5].to_vec(), items); 728 } 729 730 unsafe { 731 // Remove first of two 732 let mut list = LinkedList::new(); 733 734 push_all(&mut list, &[b.as_ref(), a.as_ref()]); 735 736 assert!(list.remove(ptr(&a)).is_some()); 737 738 assert_clean!(a); 739 740 // a should be no longer there and can't be removed twice 741 assert!(list.remove(ptr(&a)).is_none()); 742 743 assert_ptr_eq!(b, list.head); 744 assert_ptr_eq!(b, list.tail); 745 746 assert!(b.pointers.get_next().is_none()); 747 assert!(b.pointers.get_prev().is_none()); 748 749 let items = collect_list(&mut list); 750 assert_eq!([7].to_vec(), items); 751 } 752 753 unsafe { 754 // Remove last of two 755 let mut list = LinkedList::new(); 756 757 push_all(&mut list, &[b.as_ref(), a.as_ref()]); 758 759 assert!(list.remove(ptr(&b)).is_some()); 760 761 assert_clean!(b); 762 763 assert_ptr_eq!(a, list.head); 764 assert_ptr_eq!(a, list.tail); 765 766 assert!(a.pointers.get_next().is_none()); 767 assert!(a.pointers.get_prev().is_none()); 768 769 let items = collect_list(&mut list); 770 assert_eq!([5].to_vec(), items); 771 } 772 773 unsafe { 774 // Remove last item 775 let mut list = LinkedList::new(); 776 777 push_all(&mut list, &[a.as_ref()]); 778 779 assert!(list.remove(ptr(&a)).is_some()); 780 assert_clean!(a); 781 782 assert!(list.head.is_none()); 783 assert!(list.tail.is_none()); 784 let items = collect_list(&mut list); 785 assert!(items.is_empty()); 786 } 787 788 unsafe { 789 // Remove missing 790 let mut list = LinkedList::<&Entry, <&Entry as Link>::Target>::new(); 791 792 list.push_front(b.as_ref()); 793 list.push_front(a.as_ref()); 794 795 assert!(list.remove(ptr(&c)).is_none()); 796 } 797 } 798 799 #[test] count()800 fn count() { 801 let mut list = CountedLinkedList::<&Entry, <&Entry as Link>::Target>::new(); 802 assert_eq!(0, list.count()); 803 804 let a = entry(5); 805 let b = entry(7); 806 list.push_front(a.as_ref()); 807 list.push_front(b.as_ref()); 808 assert_eq!(2, list.count()); 809 810 list.pop_back(); 811 assert_eq!(1, list.count()); 812 813 unsafe { 814 list.remove(ptr(&b)); 815 } 816 assert_eq!(0, list.count()); 817 } 818 819 /// This is a fuzz test. You run it by entering `cargo fuzz run fuzz_linked_list` in CLI in `/tokio/` module. 820 #[cfg(fuzzing)] fuzz_linked_list(ops: &[u8])821 pub fn fuzz_linked_list(ops: &[u8]) { 822 enum Op { 823 Push, 824 Pop, 825 Remove(usize), 826 } 827 use std::collections::VecDeque; 828 829 let ops = ops 830 .iter() 831 .map(|i| match i % 3u8 { 832 0 => Op::Push, 833 1 => Op::Pop, 834 2 => Op::Remove((i / 3u8) as usize), 835 _ => unreachable!(), 836 }) 837 .collect::<Vec<_>>(); 838 839 let mut ll = LinkedList::<&Entry, <&Entry as Link>::Target>::new(); 840 let mut reference = VecDeque::new(); 841 842 let entries: Vec<_> = (0..ops.len()).map(|i| entry(i as i32)).collect(); 843 844 for (i, op) in ops.iter().enumerate() { 845 match op { 846 Op::Push => { 847 reference.push_front(i as i32); 848 assert_eq!(entries[i].val, i as i32); 849 850 ll.push_front(entries[i].as_ref()); 851 } 852 Op::Pop => { 853 if reference.is_empty() { 854 assert!(ll.is_empty()); 855 continue; 856 } 857 858 let v = reference.pop_back(); 859 assert_eq!(v, ll.pop_back().map(|v| v.val)); 860 } 861 Op::Remove(n) => { 862 if reference.is_empty() { 863 assert!(ll.is_empty()); 864 continue; 865 } 866 867 let idx = n % reference.len(); 868 let expect = reference.remove(idx).unwrap(); 869 870 unsafe { 871 let entry = ll.remove(ptr(&entries[expect as usize])).unwrap(); 872 assert_eq!(expect, entry.val); 873 } 874 } 875 } 876 } 877 } 878 } 879