Skip to content

Commit 1957460

Browse files
vax-rojeda
authored andcommitted
rust: list: Add examples for linked list
Add basic examples for the structure "List", which also serve as unit tests for basic list methods. It includes the following manipulations: * List creation * List emptiness check * List insertion through push_front(), push_back() * List item removal through pop_front(), pop_back() * Push one list to another through push_all_back() The method "remove()" doesn't have an example here because insertion with push_front() or push_back() will take the ownership of the item, which means we can't keep any valid reference to the node we want to remove, unless Cursor is used. The "remove" example through Cursor is already demonstrated with commit 52ae96f ("rust: list: make the cursor point between elements"). Link: #1121 Signed-off-by: I Hsin Cheng <[email protected]> Reviewed-by: Alice Ryhl <[email protected]> Reviewed-by: Benno Lossin <[email protected]> Link: https://lore.kernel.org/r/[email protected] [ Removed prelude import and spurious newlines. Formatted comments with the usual style. Reworded slightly. - Miguel ] Signed-off-by: Miguel Ojeda <[email protected]>
1 parent 28669b2 commit 1957460

File tree

1 file changed

+108
-0
lines changed

1 file changed

+108
-0
lines changed

rust/kernel/list.rs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,114 @@ pub use self::arc_field::{define_list_arc_field_getter, ListArcField};
3535
/// * All prev/next pointers in `ListLinks` fields of items in the list are valid and form a cycle.
3636
/// * For every item in the list, the list owns the associated [`ListArc`] reference and has
3737
/// exclusive access to the `ListLinks` field.
38+
///
39+
/// # Examples
40+
///
41+
/// ```
42+
/// use kernel::list::*;
43+
///
44+
/// #[pin_data]
45+
/// struct BasicItem {
46+
/// value: i32,
47+
/// #[pin]
48+
/// links: ListLinks,
49+
/// }
50+
///
51+
/// impl BasicItem {
52+
/// fn new(value: i32) -> Result<ListArc<Self>> {
53+
/// ListArc::pin_init(try_pin_init!(Self {
54+
/// value,
55+
/// links <- ListLinks::new(),
56+
/// }), GFP_KERNEL)
57+
/// }
58+
/// }
59+
///
60+
/// impl_has_list_links! {
61+
/// impl HasListLinks<0> for BasicItem { self.links }
62+
/// }
63+
/// impl_list_arc_safe! {
64+
/// impl ListArcSafe<0> for BasicItem { untracked; }
65+
/// }
66+
/// impl_list_item! {
67+
/// impl ListItem<0> for BasicItem { using ListLinks; }
68+
/// }
69+
///
70+
/// // Create a new empty list.
71+
/// let mut list = List::new();
72+
/// {
73+
/// assert!(list.is_empty());
74+
/// }
75+
///
76+
/// // Insert 3 elements using `push_back()`.
77+
/// list.push_back(BasicItem::new(15)?);
78+
/// list.push_back(BasicItem::new(10)?);
79+
/// list.push_back(BasicItem::new(30)?);
80+
///
81+
/// // Iterate over the list to verify the nodes were inserted correctly.
82+
/// // [15, 10, 30]
83+
/// {
84+
/// let mut iter = list.iter();
85+
/// assert_eq!(iter.next().unwrap().value, 15);
86+
/// assert_eq!(iter.next().unwrap().value, 10);
87+
/// assert_eq!(iter.next().unwrap().value, 30);
88+
/// assert!(iter.next().is_none());
89+
///
90+
/// // Verify the length of the list.
91+
/// assert_eq!(list.iter().count(), 3);
92+
/// }
93+
///
94+
/// // Pop the items from the list using `pop_back()` and verify the content.
95+
/// {
96+
/// assert_eq!(list.pop_back().unwrap().value, 30);
97+
/// assert_eq!(list.pop_back().unwrap().value, 10);
98+
/// assert_eq!(list.pop_back().unwrap().value, 15);
99+
/// }
100+
///
101+
/// // Insert 3 elements using `push_front()`.
102+
/// list.push_front(BasicItem::new(15)?);
103+
/// list.push_front(BasicItem::new(10)?);
104+
/// list.push_front(BasicItem::new(30)?);
105+
///
106+
/// // Iterate over the list to verify the nodes were inserted correctly.
107+
/// // [30, 10, 15]
108+
/// {
109+
/// let mut iter = list.iter();
110+
/// assert_eq!(iter.next().unwrap().value, 30);
111+
/// assert_eq!(iter.next().unwrap().value, 10);
112+
/// assert_eq!(iter.next().unwrap().value, 15);
113+
/// assert!(iter.next().is_none());
114+
///
115+
/// // Verify the length of the list.
116+
/// assert_eq!(list.iter().count(), 3);
117+
/// }
118+
///
119+
/// // Pop the items from the list using `pop_front()` and verify the content.
120+
/// {
121+
/// assert_eq!(list.pop_front().unwrap().value, 30);
122+
/// assert_eq!(list.pop_front().unwrap().value, 10);
123+
/// }
124+
///
125+
/// // Push `list2` to `list` through `push_all_back()`.
126+
/// // list: [15]
127+
/// // list2: [25, 35]
128+
/// {
129+
/// let mut list2 = List::new();
130+
/// list2.push_back(BasicItem::new(25)?);
131+
/// list2.push_back(BasicItem::new(35)?);
132+
///
133+
/// list.push_all_back(&mut list2);
134+
///
135+
/// // list: [15, 25, 35]
136+
/// // list2: []
137+
/// let mut iter = list.iter();
138+
/// assert_eq!(iter.next().unwrap().value, 15);
139+
/// assert_eq!(iter.next().unwrap().value, 25);
140+
/// assert_eq!(iter.next().unwrap().value, 35);
141+
/// assert!(iter.next().is_none());
142+
/// assert!(list2.is_empty());
143+
/// }
144+
/// # Result::<(), Error>::Ok(())
145+
/// ```
38146
pub struct List<T: ?Sized + ListItem<ID>, const ID: u64 = 0> {
39147
first: *mut ListLinksFields,
40148
_ty: PhantomData<ListArc<T, ID>>,

0 commit comments

Comments
 (0)