Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rust: list: make the cursor point between elements

I've been using the linked list cursor for a few different things, and I
find it inconvenient to use because all of the functions have signatures
along the lines of `Self -> Option<Self>`. The root cause of these
signatures is that the cursor points *at* an element, rather than
*between* two elements.

Thus, change the cursor API to point between two elements. This is
inspired by the stdlib linked list (well, really by this guy [1]), which
also uses cursors that point between elements.

The `peek_next` method returns a helper that lets you look at and
optionally remove the element, as one common use-case of cursors is to
iterate a list to look for an element, then remove that element.

For many of the methods, this will reduce how many we need since they
now just need a prev/next method, instead of the current state where you
may end up needing all of curr/prev/next. Also, if we decide to add a
function for splitting a list into two lists at the cursor, then a
cursor that points between elements is exactly what makes the most
sense.

Another advantage is that this means you can now have a cursor into an
empty list.

Link: https://rust-unofficial.github.io/too-many-lists/sixth-cursors-intro.html [1]
Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>
Reviewed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Link: https://lore.kernel.org/r/20250210-cursor-between-v7-2-36f0215181ed@google.com
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>

authored by

Alice Ryhl and committed by
Miguel Ojeda
52ae96f5 998c6573

+349 -56
+349 -56
rust/kernel/list.rs
··· 483 483 other.first = ptr::null_mut(); 484 484 } 485 485 486 - /// Returns a cursor to the first element of the list. 487 - /// 488 - /// If the list is empty, this returns `None`. 489 - pub fn cursor_front(&mut self) -> Option<Cursor<'_, T, ID>> { 490 - if self.first.is_null() { 491 - None 492 - } else { 493 - Some(Cursor { 494 - current: self.first, 495 - list: self, 496 - }) 486 + /// Returns a cursor that points before the first element of the list. 487 + pub fn cursor_front(&mut self) -> Cursor<'_, T, ID> { 488 + // INVARIANT: `self.first` is in this list. 489 + Cursor { 490 + next: self.first, 491 + list: self, 492 + } 493 + } 494 + 495 + /// Returns a cursor that points after the last element in the list. 496 + pub fn cursor_back(&mut self) -> Cursor<'_, T, ID> { 497 + // INVARIANT: `next` is allowed to be null. 498 + Cursor { 499 + next: core::ptr::null_mut(), 500 + list: self, 497 501 } 498 502 } 499 503 ··· 577 573 578 574 /// A cursor into a [`List`]. 579 575 /// 576 + /// A cursor always rests between two elements in the list. This means that a cursor has a previous 577 + /// and next element, but no current element. It also means that it's possible to have a cursor 578 + /// into an empty list. 579 + /// 580 + /// # Examples 581 + /// 582 + /// ``` 583 + /// use kernel::prelude::*; 584 + /// use kernel::list::{List, ListArc, ListLinks}; 585 + /// 586 + /// #[pin_data] 587 + /// struct ListItem { 588 + /// value: u32, 589 + /// #[pin] 590 + /// links: ListLinks, 591 + /// } 592 + /// 593 + /// impl ListItem { 594 + /// fn new(value: u32) -> Result<ListArc<Self>> { 595 + /// ListArc::pin_init(try_pin_init!(Self { 596 + /// value, 597 + /// links <- ListLinks::new(), 598 + /// }), GFP_KERNEL) 599 + /// } 600 + /// } 601 + /// 602 + /// kernel::list::impl_has_list_links! { 603 + /// impl HasListLinks<0> for ListItem { self.links } 604 + /// } 605 + /// kernel::list::impl_list_arc_safe! { 606 + /// impl ListArcSafe<0> for ListItem { untracked; } 607 + /// } 608 + /// kernel::list::impl_list_item! { 609 + /// impl ListItem<0> for ListItem { using ListLinks; } 610 + /// } 611 + /// 612 + /// // Use a cursor to remove the first element with the given value. 613 + /// fn remove_first(list: &mut List<ListItem>, value: u32) -> Option<ListArc<ListItem>> { 614 + /// let mut cursor = list.cursor_front(); 615 + /// while let Some(next) = cursor.peek_next() { 616 + /// if next.value == value { 617 + /// return Some(next.remove()); 618 + /// } 619 + /// cursor.move_next(); 620 + /// } 621 + /// None 622 + /// } 623 + /// 624 + /// // Use a cursor to remove the last element with the given value. 625 + /// fn remove_last(list: &mut List<ListItem>, value: u32) -> Option<ListArc<ListItem>> { 626 + /// let mut cursor = list.cursor_back(); 627 + /// while let Some(prev) = cursor.peek_prev() { 628 + /// if prev.value == value { 629 + /// return Some(prev.remove()); 630 + /// } 631 + /// cursor.move_prev(); 632 + /// } 633 + /// None 634 + /// } 635 + /// 636 + /// // Use a cursor to remove all elements with the given value. The removed elements are moved to 637 + /// // a new list. 638 + /// fn remove_all(list: &mut List<ListItem>, value: u32) -> List<ListItem> { 639 + /// let mut out = List::new(); 640 + /// let mut cursor = list.cursor_front(); 641 + /// while let Some(next) = cursor.peek_next() { 642 + /// if next.value == value { 643 + /// out.push_back(next.remove()); 644 + /// } else { 645 + /// cursor.move_next(); 646 + /// } 647 + /// } 648 + /// out 649 + /// } 650 + /// 651 + /// // Use a cursor to insert a value at a specific index. Returns an error if the index is out of 652 + /// // bounds. 653 + /// fn insert_at(list: &mut List<ListItem>, new: ListArc<ListItem>, idx: usize) -> Result { 654 + /// let mut cursor = list.cursor_front(); 655 + /// for _ in 0..idx { 656 + /// if !cursor.move_next() { 657 + /// return Err(EINVAL); 658 + /// } 659 + /// } 660 + /// cursor.insert_next(new); 661 + /// Ok(()) 662 + /// } 663 + /// 664 + /// // Merge two sorted lists into a single sorted list. 665 + /// fn merge_sorted(list: &mut List<ListItem>, merge: List<ListItem>) { 666 + /// let mut cursor = list.cursor_front(); 667 + /// for to_insert in merge { 668 + /// while let Some(next) = cursor.peek_next() { 669 + /// if to_insert.value < next.value { 670 + /// break; 671 + /// } 672 + /// cursor.move_next(); 673 + /// } 674 + /// cursor.insert_prev(to_insert); 675 + /// } 676 + /// } 677 + /// 678 + /// let mut list = List::new(); 679 + /// list.push_back(ListItem::new(14)?); 680 + /// list.push_back(ListItem::new(12)?); 681 + /// list.push_back(ListItem::new(10)?); 682 + /// list.push_back(ListItem::new(12)?); 683 + /// list.push_back(ListItem::new(15)?); 684 + /// list.push_back(ListItem::new(14)?); 685 + /// assert_eq!(remove_all(&mut list, 12).iter().count(), 2); 686 + /// // [14, 10, 15, 14] 687 + /// assert!(remove_first(&mut list, 14).is_some()); 688 + /// // [10, 15, 14] 689 + /// insert_at(&mut list, ListItem::new(12)?, 2)?; 690 + /// // [10, 15, 12, 14] 691 + /// assert!(remove_last(&mut list, 15).is_some()); 692 + /// // [10, 12, 14] 693 + /// 694 + /// let mut list2 = List::new(); 695 + /// list2.push_back(ListItem::new(11)?); 696 + /// list2.push_back(ListItem::new(13)?); 697 + /// merge_sorted(&mut list, list2); 698 + /// 699 + /// let mut items = list.into_iter(); 700 + /// assert_eq!(items.next().unwrap().value, 10); 701 + /// assert_eq!(items.next().unwrap().value, 11); 702 + /// assert_eq!(items.next().unwrap().value, 12); 703 + /// assert_eq!(items.next().unwrap().value, 13); 704 + /// assert_eq!(items.next().unwrap().value, 14); 705 + /// assert!(items.next().is_none()); 706 + /// # Result::<(), Error>::Ok(()) 707 + /// ``` 708 + /// 580 709 /// # Invariants 581 710 /// 582 - /// The `current` pointer points a value in `list`. 711 + /// The `next` pointer is null or points a value in `list`. 583 712 pub struct Cursor<'a, T: ?Sized + ListItem<ID>, const ID: u64 = 0> { 584 - current: *mut ListLinksFields, 585 713 list: &'a mut List<T, ID>, 714 + /// Points at the element after this cursor, or null if the cursor is after the last element. 715 + next: *mut ListLinksFields, 586 716 } 587 717 588 718 impl<'a, T: ?Sized + ListItem<ID>, const ID: u64> Cursor<'a, T, ID> { 589 - /// Access the current element of this cursor. 590 - pub fn current(&self) -> ArcBorrow<'_, T> { 591 - // SAFETY: The `current` pointer points a value in the list. 592 - let me = unsafe { T::view_value(ListLinks::from_fields(self.current)) }; 719 + /// Returns a pointer to the element before the cursor. 720 + /// 721 + /// Returns null if there is no element before the cursor. 722 + fn prev_ptr(&self) -> *mut ListLinksFields { 723 + let mut next = self.next; 724 + let first = self.list.first; 725 + if next == first { 726 + // We are before the first element. 727 + return core::ptr::null_mut(); 728 + } 729 + 730 + if next.is_null() { 731 + // We are after the last element, so we need a pointer to the last element, which is 732 + // the same as `(*first).prev`. 733 + next = first; 734 + } 735 + 736 + // SAFETY: `next` can't be null, because then `first` must also be null, but in that case 737 + // we would have exited at the `next == first` check. Thus, `next` is an element in the 738 + // list, so we can access its `prev` pointer. 739 + unsafe { (*next).prev } 740 + } 741 + 742 + /// Access the element after this cursor. 743 + pub fn peek_next(&mut self) -> Option<CursorPeek<'_, 'a, T, true, ID>> { 744 + if self.next.is_null() { 745 + return None; 746 + } 747 + 748 + // INVARIANT: 749 + // * We just checked that `self.next` is non-null, so it must be in `self.list`. 750 + // * `ptr` is equal to `self.next`. 751 + Some(CursorPeek { 752 + ptr: self.next, 753 + cursor: self, 754 + }) 755 + } 756 + 757 + /// Access the element before this cursor. 758 + pub fn peek_prev(&mut self) -> Option<CursorPeek<'_, 'a, T, false, ID>> { 759 + let prev = self.prev_ptr(); 760 + 761 + if prev.is_null() { 762 + return None; 763 + } 764 + 765 + // INVARIANT: 766 + // * We just checked that `prev` is non-null, so it must be in `self.list`. 767 + // * `self.prev_ptr()` never returns `self.next`. 768 + Some(CursorPeek { 769 + ptr: prev, 770 + cursor: self, 771 + }) 772 + } 773 + 774 + /// Move the cursor one element forward. 775 + /// 776 + /// If the cursor is after the last element, then this call does nothing. This call returns 777 + /// `true` if the cursor's position was changed. 778 + pub fn move_next(&mut self) -> bool { 779 + if self.next.is_null() { 780 + return false; 781 + } 782 + 783 + // SAFETY: `self.next` is an element in the list and we borrow the list mutably, so we can 784 + // access the `next` field. 785 + let mut next = unsafe { (*self.next).next }; 786 + 787 + if next == self.list.first { 788 + next = core::ptr::null_mut(); 789 + } 790 + 791 + // INVARIANT: `next` is either null or the next element after an element in the list. 792 + self.next = next; 793 + true 794 + } 795 + 796 + /// Move the cursor one element backwards. 797 + /// 798 + /// If the cursor is before the first element, then this call does nothing. This call returns 799 + /// `true` if the cursor's position was changed. 800 + pub fn move_prev(&mut self) -> bool { 801 + if self.next == self.list.first { 802 + return false; 803 + } 804 + 805 + // INVARIANT: `prev_ptr()` always returns a pointer that is null or in the list. 806 + self.next = self.prev_ptr(); 807 + true 808 + } 809 + 810 + /// Inserts an element where the cursor is pointing and get a pointer to the new element. 811 + fn insert_inner(&mut self, item: ListArc<T, ID>) -> *mut ListLinksFields { 812 + let ptr = if self.next.is_null() { 813 + self.list.first 814 + } else { 815 + self.next 816 + }; 817 + // SAFETY: 818 + // * `ptr` is an element in the list or null. 819 + // * if `ptr` is null, then `self.list.first` is null so the list is empty. 820 + let item = unsafe { self.list.insert_inner(item, ptr) }; 821 + if self.next == self.list.first { 822 + // INVARIANT: We just inserted `item`, so it's a member of list. 823 + self.list.first = item; 824 + } 825 + item 826 + } 827 + 828 + /// Insert an element at this cursor's location. 829 + pub fn insert(mut self, item: ListArc<T, ID>) { 830 + // This is identical to `insert_prev`, but consumes the cursor. This is helpful because it 831 + // reduces confusion when the last operation on the cursor is an insertion; in that case, 832 + // you just want to insert the element at the cursor, and it is confusing that the call 833 + // involves the word prev or next. 834 + self.insert_inner(item); 835 + } 836 + 837 + /// Inserts an element after this cursor. 838 + /// 839 + /// After insertion, the new element will be after the cursor. 840 + pub fn insert_next(&mut self, item: ListArc<T, ID>) { 841 + self.next = self.insert_inner(item); 842 + } 843 + 844 + /// Inserts an element before this cursor. 845 + /// 846 + /// After insertion, the new element will be before the cursor. 847 + pub fn insert_prev(&mut self, item: ListArc<T, ID>) { 848 + self.insert_inner(item); 849 + } 850 + 851 + /// Remove the next element from the list. 852 + pub fn remove_next(&mut self) -> Option<ListArc<T, ID>> { 853 + self.peek_next().map(|v| v.remove()) 854 + } 855 + 856 + /// Remove the previous element from the list. 857 + pub fn remove_prev(&mut self) -> Option<ListArc<T, ID>> { 858 + self.peek_prev().map(|v| v.remove()) 859 + } 860 + } 861 + 862 + /// References the element in the list next to the cursor. 863 + /// 864 + /// # Invariants 865 + /// 866 + /// * `ptr` is an element in `self.cursor.list`. 867 + /// * `ISNEXT == (self.ptr == self.cursor.next)`. 868 + pub struct CursorPeek<'a, 'b, T: ?Sized + ListItem<ID>, const ISNEXT: bool, const ID: u64> { 869 + cursor: &'a mut Cursor<'b, T, ID>, 870 + ptr: *mut ListLinksFields, 871 + } 872 + 873 + impl<'a, 'b, T: ?Sized + ListItem<ID>, const ISNEXT: bool, const ID: u64> 874 + CursorPeek<'a, 'b, T, ISNEXT, ID> 875 + { 876 + /// Remove the element from the list. 877 + pub fn remove(self) -> ListArc<T, ID> { 878 + if ISNEXT { 879 + self.cursor.move_next(); 880 + } 881 + 882 + // INVARIANT: `self.ptr` is not equal to `self.cursor.next` due to the above `move_next` 883 + // call. 884 + // SAFETY: By the type invariants of `Self`, `next` is not null, so `next` is an element of 885 + // `self.cursor.list` by the type invariants of `Cursor`. 886 + unsafe { self.cursor.list.remove_internal(self.ptr) } 887 + } 888 + 889 + /// Access this value as an [`ArcBorrow`]. 890 + pub fn arc(&self) -> ArcBorrow<'_, T> { 891 + // SAFETY: `self.ptr` points at an element in `self.cursor.list`. 892 + let me = unsafe { T::view_value(ListLinks::from_fields(self.ptr)) }; 593 893 // SAFETY: 594 894 // * All values in a list are stored in an `Arc`. 595 895 // * The value cannot be removed from the list for the duration of the lifetime annotated 596 896 // on the returned `ArcBorrow`, because removing it from the list would require mutable 597 - // access to the cursor or the list. However, the `ArcBorrow` holds an immutable borrow 598 - // on the cursor, which in turn holds a mutable borrow on the list, so any such 599 - // mutable access requires first releasing the immutable borrow on the cursor. 897 + // access to the `CursorPeek`, the `Cursor` or the `List`. However, the `ArcBorrow` holds 898 + // an immutable borrow on the `CursorPeek`, which in turn holds a mutable borrow on the 899 + // `Cursor`, which in turn holds a mutable borrow on the `List`, so any such mutable 900 + // access requires first releasing the immutable borrow on the `CursorPeek`. 600 901 // * Values in a list never have a `UniqueArc` reference, because the list has a `ListArc` 601 902 // reference, and `UniqueArc` references must be unique. 602 903 unsafe { ArcBorrow::from_raw(me) } 603 904 } 905 + } 604 906 605 - /// Move the cursor to the next element. 606 - pub fn next(self) -> Option<Cursor<'a, T, ID>> { 607 - // SAFETY: The `current` field is always in a list. 608 - let next = unsafe { (*self.current).next }; 907 + impl<'a, 'b, T: ?Sized + ListItem<ID>, const ISNEXT: bool, const ID: u64> core::ops::Deref 908 + for CursorPeek<'a, 'b, T, ISNEXT, ID> 909 + { 910 + // If you change the `ptr` field to have type `ArcBorrow<'a, T>`, it might seem like you could 911 + // get rid of the `CursorPeek::arc` method and change the deref target to `ArcBorrow<'a, T>`. 912 + // However, that doesn't work because 'a is too long. You could obtain an `ArcBorrow<'a, T>` 913 + // and then call `CursorPeek::remove` without giving up the `ArcBorrow<'a, T>`, which would be 914 + // unsound. 915 + type Target = T; 609 916 610 - if next == self.list.first { 611 - None 612 - } else { 613 - // INVARIANT: Since `self.current` is in the `list`, its `next` pointer is also in the 614 - // `list`. 615 - Some(Cursor { 616 - current: next, 617 - list: self.list, 618 - }) 619 - } 620 - } 917 + fn deref(&self) -> &T { 918 + // SAFETY: `self.ptr` points at an element in `self.cursor.list`. 919 + let me = unsafe { T::view_value(ListLinks::from_fields(self.ptr)) }; 621 920 622 - /// Move the cursor to the previous element. 623 - pub fn prev(self) -> Option<Cursor<'a, T, ID>> { 624 - // SAFETY: The `current` field is always in a list. 625 - let prev = unsafe { (*self.current).prev }; 626 - 627 - if self.current == self.list.first { 628 - None 629 - } else { 630 - // INVARIANT: Since `self.current` is in the `list`, its `prev` pointer is also in the 631 - // `list`. 632 - Some(Cursor { 633 - current: prev, 634 - list: self.list, 635 - }) 636 - } 637 - } 638 - 639 - /// Remove the current element from the list. 640 - pub fn remove(self) -> ListArc<T, ID> { 641 - // SAFETY: The `current` pointer always points at a member of the list. 642 - unsafe { self.list.remove_internal(self.current) } 921 + // SAFETY: The value cannot be removed from the list for the duration of the lifetime 922 + // annotated on the returned `&T`, because removing it from the list would require mutable 923 + // access to the `CursorPeek`, the `Cursor` or the `List`. However, the `&T` holds an 924 + // immutable borrow on the `CursorPeek`, which in turn holds a mutable borrow on the 925 + // `Cursor`, which in turn holds a mutable borrow on the `List`, so any such mutable access 926 + // requires first releasing the immutable borrow on the `CursorPeek`. 927 + unsafe { &*me } 643 928 } 644 929 } 645 930