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: Add an example for `ListLinksSelfPtr` usage

It appears that the support for `ListLinksSelfPtr` is dead code at the
moment [1]. Although some tests were added at [2] for impl `ListItem`
using `ListLinksSelfPtr` field, still we could use more examples
demonstrating and testing the usage of `ListLinksSelfPtr`. Hence add an
example similar to `ListLinks` usage.

The example is mostly based on Alice's usage in binder driver [3].

Link: https://lore.kernel.org/rust-for-linux/20250719183649.596051-1-ojeda@kernel.org/ [1]
Link: https://lore.kernel.org/rust-for-linux/20250709-list-no-offset-v4-5-a429e75840a9@gmail.com/ [2]
Link: https://lore.kernel.org/rust-for-linux/20231101-rust-binder-v1-4-08ba9197f637@google.com/ [3]
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
[ Fixed typo. - Miguel ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>

authored by

Boqun Feng and committed by
Miguel Ojeda
bf87a41b a15d12c2

+120
+120
rust/kernel/list.rs
··· 38 38 /// 39 39 /// # Examples 40 40 /// 41 + /// Use [`ListLinks`] as the type of the intrusive field. 42 + /// 41 43 /// ``` 42 44 /// use kernel::list::*; 43 45 /// ··· 137 135 /// assert_eq!(iter.next().ok_or(EINVAL)?.value, 15); 138 136 /// assert_eq!(iter.next().ok_or(EINVAL)?.value, 25); 139 137 /// assert_eq!(iter.next().ok_or(EINVAL)?.value, 35); 138 + /// assert!(iter.next().is_none()); 139 + /// assert!(list2.is_empty()); 140 + /// } 141 + /// # Result::<(), Error>::Ok(()) 142 + /// ``` 143 + /// 144 + /// Use [`ListLinksSelfPtr`] as the type of the intrusive field. This allows a list of trait object 145 + /// type. 146 + /// 147 + /// ``` 148 + /// use kernel::list::*; 149 + /// 150 + /// trait Foo { 151 + /// fn foo(&self) -> (&'static str, i32); 152 + /// } 153 + /// 154 + /// #[pin_data] 155 + /// struct DTWrap<T: ?Sized> { 156 + /// #[pin] 157 + /// links: ListLinksSelfPtr<DTWrap<dyn Foo>>, 158 + /// value: T, 159 + /// } 160 + /// 161 + /// impl<T> DTWrap<T> { 162 + /// fn new(value: T) -> Result<ListArc<Self>> { 163 + /// ListArc::pin_init(try_pin_init!(Self { 164 + /// value, 165 + /// links <- ListLinksSelfPtr::new(), 166 + /// }), GFP_KERNEL) 167 + /// } 168 + /// } 169 + /// 170 + /// impl_list_arc_safe! { 171 + /// impl{T: ?Sized} ListArcSafe<0> for DTWrap<T> { untracked; } 172 + /// } 173 + /// impl_list_item! { 174 + /// impl ListItem<0> for DTWrap<dyn Foo> { using ListLinksSelfPtr { self.links }; } 175 + /// } 176 + /// 177 + /// // Create a new empty list. 178 + /// let mut list = List::<DTWrap<dyn Foo>>::new(); 179 + /// { 180 + /// assert!(list.is_empty()); 181 + /// } 182 + /// 183 + /// struct A(i32); 184 + /// // `A` returns the inner value for `foo`. 185 + /// impl Foo for A { fn foo(&self) -> (&'static str, i32) { ("a", self.0) } } 186 + /// 187 + /// struct B; 188 + /// // `B` always returns 42. 189 + /// impl Foo for B { fn foo(&self) -> (&'static str, i32) { ("b", 42) } } 190 + /// 191 + /// // Insert 3 element using `push_back()`. 192 + /// list.push_back(DTWrap::new(A(15))?); 193 + /// list.push_back(DTWrap::new(A(32))?); 194 + /// list.push_back(DTWrap::new(B)?); 195 + /// 196 + /// // Iterate over the list to verify the nodes were inserted correctly. 197 + /// // [A(15), A(32), B] 198 + /// { 199 + /// let mut iter = list.iter(); 200 + /// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("a", 15)); 201 + /// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("a", 32)); 202 + /// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("b", 42)); 203 + /// assert!(iter.next().is_none()); 204 + /// 205 + /// // Verify the length of the list. 206 + /// assert_eq!(list.iter().count(), 3); 207 + /// } 208 + /// 209 + /// // Pop the items from the list using `pop_back()` and verify the content. 210 + /// { 211 + /// assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("b", 42)); 212 + /// assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("a", 32)); 213 + /// assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("a", 15)); 214 + /// } 215 + /// 216 + /// // Insert 3 elements using `push_front()`. 217 + /// list.push_front(DTWrap::new(A(15))?); 218 + /// list.push_front(DTWrap::new(A(32))?); 219 + /// list.push_front(DTWrap::new(B)?); 220 + /// 221 + /// // Iterate over the list to verify the nodes were inserted correctly. 222 + /// // [B, A(32), A(15)] 223 + /// { 224 + /// let mut iter = list.iter(); 225 + /// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("b", 42)); 226 + /// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("a", 32)); 227 + /// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("a", 15)); 228 + /// assert!(iter.next().is_none()); 229 + /// 230 + /// // Verify the length of the list. 231 + /// assert_eq!(list.iter().count(), 3); 232 + /// } 233 + /// 234 + /// // Pop the items from the list using `pop_front()` and verify the content. 235 + /// { 236 + /// assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("a", 15)); 237 + /// assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("a", 32)); 238 + /// } 239 + /// 240 + /// // Push `list2` to `list` through `push_all_back()`. 241 + /// // list: [B] 242 + /// // list2: [B, A(25)] 243 + /// { 244 + /// let mut list2 = List::<DTWrap<dyn Foo>>::new(); 245 + /// list2.push_back(DTWrap::new(B)?); 246 + /// list2.push_back(DTWrap::new(A(25))?); 247 + /// 248 + /// list.push_all_back(&mut list2); 249 + /// 250 + /// // list: [B, B, A(25)] 251 + /// // list2: [] 252 + /// let mut iter = list.iter(); 253 + /// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("b", 42)); 254 + /// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("b", 42)); 255 + /// assert_eq!(iter.next().ok_or(EINVAL)?.value.foo(), ("a", 25)); 140 256 /// assert!(iter.next().is_none()); 141 257 /// assert!(list2.is_empty()); 142 258 /// }