rustpython_common/linked_list.rs
1// spell-checker:disable
2
3//! This module is modified from tokio::util::linked_list: <https://github.com/tokio-rs/tokio/blob/master/tokio/src/util/linked_list.rs>
4//! Tokio is licensed under the MIT license:
5//!
6//! Copyright (c) 2021 Tokio Contributors
7//!
8//! Permission is hereby granted, free of charge, to any
9//! person obtaining a copy of this software and associated
10//! documentation files (the "Software"), to deal in the
11//! Software without restriction, including without
12//! limitation the rights to use, copy, modify, merge,
13//! publish, distribute, sublicense, and/or sell copies of
14//! the Software, and to permit persons to whom the Software
15//! is furnished to do so, subject to the following
16//! conditions:
17//!
18//! The above copyright notice and this permission notice
19//! shall be included in all copies or substantial portions
20//! of the Software.
21//!
22//! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
23//! ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
24//! TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
25//! PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
26//! SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
27//! CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28//! OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
29//! IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30//! DEALINGS IN THE SOFTWARE.
31//!
32//! Original header:
33//!
34//! An intrusive double linked list of data.
35//!
36//! The data structure supports tracking pinned nodes. Most of the data
37//! structure's APIs are `unsafe` as they require the caller to ensure the
38//! specified node is actually contained by the list.
39
40#![allow(clippy::new_without_default, clippy::missing_safety_doc)]
41// It doesn't make sense to enforce `unsafe_op_in_unsafe_fn` for this module because
42//
43// * The intrusive linked list naturally relies on unsafe operations.
44// * Excessive `unsafe {}` blocks hurt readability significantly.
45#![expect(unsafe_op_in_unsafe_fn)]
46
47use core::cell::UnsafeCell;
48use core::fmt;
49use core::marker::PhantomPinned;
50use core::mem::ManuallyDrop;
51use core::ptr::{self, NonNull};
52
53/// An intrusive linked list.
54///
55/// Currently, the list is not emptied on drop. It is the caller's
56/// responsibility to ensure the list is empty before dropping it.
57pub struct LinkedList<L: Link> {
58 /// Linked list head
59 head: Option<NonNull<L::Target>>,
60 // /// Linked list tail
61 // tail: Option<NonNull<T>>,
62}
63
64unsafe impl<L: Link> Send for LinkedList<L> where L::Target: Send {}
65unsafe impl<L: Link> Sync for LinkedList<L> where L::Target: Sync {}
66
67/// Defines how a type is tracked within a linked list.
68///
69/// In order to support storing a single type within multiple lists, accessing
70/// the list pointers is decoupled from the entry type.
71///
72/// # Safety
73///
74/// Implementations must guarantee that `Target` types are pinned in memory. In
75/// other words, when a node is inserted, the value will not be moved as long as
76/// it is stored in the list.
77pub unsafe trait Link {
78 /// Handle to the list entry.
79 ///
80 /// This is usually a pointer-ish type.
81 type Handle;
82
83 /// Node type.
84 type Target;
85
86 /// Convert the handle to a raw pointer without consuming the handle.
87 fn as_raw(handle: &Self::Handle) -> NonNull<Self::Target>;
88
89 /// Convert the raw pointer to a handle
90 unsafe fn from_raw(ptr: NonNull<Self::Target>) -> Self::Handle;
91
92 /// Return the pointers for a node
93 ///
94 /// # Safety
95 ///
96 /// The resulting pointer should have the same tag in the stacked-borrows
97 /// stack as the argument. In particular, the method may not create an
98 /// intermediate reference in the process of creating the resulting raw
99 /// pointer.
100 ///
101 /// The `target` pointer must be valid.
102 unsafe fn pointers(target: NonNull<Self::Target>) -> NonNull<Pointers<Self::Target>>;
103}
104
105/// Previous / next pointers.
106pub struct Pointers<T> {
107 inner: UnsafeCell<PointersInner<T>>,
108}
109
110/// We do not want the compiler to put the `noalias` attribute on mutable
111/// references to this type, so the type has been made `!Unpin` with a
112/// `PhantomPinned` field.
113///
114/// Additionally, we never access the `prev` or `next` fields directly, as any
115/// such access would implicitly involve the creation of a reference to the
116/// field, which we want to avoid since the fields are not `!Unpin`, and would
117/// hence be given the `noalias` attribute if we were to do such an access. As
118/// an alternative to accessing the fields directly, the [`Pointers`] type
119/// provides getters and setters for the two fields, and those are implemented
120/// using `ptr`-specific methods which avoids the creation of intermediate
121/// references.
122///
123/// See this link for more information:
124/// <https://github.com/rust-lang/rust/pull/82834>
125struct PointersInner<T> {
126 /// The previous node in the list. [`None`] if there is no previous node.
127 prev: Option<NonNull<T>>,
128
129 /// The next node in the list. [`None`] if there is no previous node.
130 next: Option<NonNull<T>>,
131
132 /// This type is !Unpin due to the heuristic from:
133 /// <https://github.com/rust-lang/rust/pull/82834>
134 _pin: PhantomPinned,
135}
136
137unsafe impl<T: Send> Send for Pointers<T> {}
138unsafe impl<T: Sync> Sync for Pointers<T> {}
139
140// ===== impl LinkedList =====
141
142impl<L: Link> LinkedList<L> {
143 /// Creates an empty linked list.
144 #[must_use]
145 pub const fn new() -> Self {
146 Self {
147 head: None,
148 // tail: None,
149 }
150 }
151
152 /// Adds an element first in the list.
153 pub fn push_front(&mut self, val: L::Handle) {
154 // The value should not be dropped, it is being inserted into the list
155 let val = ManuallyDrop::new(val);
156 let ptr = L::as_raw(&val);
157 assert_ne!(self.head, Some(ptr));
158 unsafe {
159 // Verify the node is not already in a list (pointers must be clean)
160 debug_assert!(
161 L::pointers(ptr).as_ref().get_prev().is_none(),
162 "push_front: node already has prev pointer (double-insert?)"
163 );
164 debug_assert!(
165 L::pointers(ptr).as_ref().get_next().is_none(),
166 "push_front: node already has next pointer (double-insert?)"
167 );
168
169 L::pointers(ptr).as_mut().set_next(self.head);
170 L::pointers(ptr).as_mut().set_prev(None);
171
172 if let Some(head) = self.head {
173 L::pointers(head).as_mut().set_prev(Some(ptr));
174 }
175
176 self.head = Some(ptr);
177
178 // if self.tail.is_none() {
179 // self.tail = Some(ptr);
180 // }
181 }
182 }
183
184 // /// Removes the last element from a list and returns it, or None if it is
185 // /// empty.
186 // pub fn pop_back(&mut self) -> Option<L::Handle> {
187 // unsafe {
188 // let last = self.tail?;
189 // self.tail = L::pointers(last).as_ref().get_prev();
190
191 // if let Some(prev) = L::pointers(last).as_ref().get_prev() {
192 // L::pointers(prev).as_mut().set_next(None);
193 // } else {
194 // self.head = None
195 // }
196
197 // L::pointers(last).as_mut().set_prev(None);
198 // L::pointers(last).as_mut().set_next(None);
199
200 // Some(L::from_raw(last))
201 // }
202 // }
203
204 /// Removes the first element from the list and returns it, or None if empty.
205 pub fn pop_front(&mut self) -> Option<L::Handle> {
206 let head = self.head?;
207 unsafe {
208 self.head = L::pointers(head).as_ref().get_next();
209 if let Some(new_head) = self.head {
210 L::pointers(new_head).as_mut().set_prev(None);
211 }
212
213 L::pointers(head).as_mut().set_next(None);
214 L::pointers(head).as_mut().set_prev(None);
215 Some(L::from_raw(head))
216 }
217 }
218
219 /// Returns whether the linked list does not contain any node
220 #[must_use]
221 pub const fn is_empty(&self) -> bool {
222 self.head.is_none()
223 // if self.head.is_some() {
224 // return false;
225 // }
226
227 // assert!(self.tail.is_none());
228 // true
229 }
230
231 /// Removes the specified node from the list
232 ///
233 /// # Safety
234 ///
235 /// The caller **must** ensure that `node` is currently contained by
236 /// `self` or not contained by any other list.
237 pub unsafe fn remove(&mut self, node: NonNull<L::Target>) -> Option<L::Handle> {
238 if let Some(prev) = L::pointers(node).as_ref().get_prev() {
239 debug_assert_eq!(
240 L::pointers(prev).as_ref().get_next(),
241 Some(node),
242 "linked list corruption: prev->next != node (prev={prev:p}, node={node:p})"
243 );
244 L::pointers(prev)
245 .as_mut()
246 .set_next(L::pointers(node).as_ref().get_next());
247 } else {
248 if self.head != Some(node) {
249 return None;
250 }
251
252 self.head = L::pointers(node).as_ref().get_next();
253 }
254
255 if let Some(next) = L::pointers(node).as_ref().get_next() {
256 debug_assert_eq!(
257 L::pointers(next).as_ref().get_prev(),
258 Some(node),
259 "linked list corruption: next->prev != node (next={next:p}, node={node:p})"
260 );
261 L::pointers(next)
262 .as_mut()
263 .set_prev(L::pointers(node).as_ref().get_prev());
264 } else {
265 // // This might be the last item in the list
266 // if self.tail != Some(node) {
267 // return None;
268 // }
269
270 // self.tail = L::pointers(node).as_ref().get_prev();
271 }
272
273 L::pointers(node).as_mut().set_next(None);
274 L::pointers(node).as_mut().set_prev(None);
275
276 Some(L::from_raw(node))
277 }
278
279 // pub fn last(&self) -> Option<&L::Target> {
280 // let tail = self.tail.as_ref()?;
281 // unsafe { Some(&*tail.as_ptr()) }
282 // }
283
284 // === rustpython additions ===
285
286 pub fn iter(&self) -> impl Iterator<Item = &L::Target> {
287 core::iter::successors(self.head, |node| unsafe {
288 L::pointers(*node).as_ref().get_next()
289 })
290 .map(|ptr| unsafe { ptr.as_ref() })
291 }
292}
293
294impl<L: Link> fmt::Debug for LinkedList<L> {
295 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
296 f.debug_struct("LinkedList")
297 .field("head", &self.head)
298 // .field("tail", &self.tail)
299 .finish()
300 }
301}
302
303impl<L: Link> Default for LinkedList<L> {
304 fn default() -> Self {
305 Self::new()
306 }
307}
308
309// ===== impl DrainFilter =====
310
311pub struct DrainFilter<'a, L: Link, F> {
312 list: &'a mut LinkedList<L>,
313 filter: F,
314 curr: Option<NonNull<L::Target>>,
315}
316
317impl<L: Link> LinkedList<L> {
318 pub const fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<'_, L, F>
319 where
320 F: FnMut(&L::Target) -> bool,
321 {
322 let curr = self.head;
323 DrainFilter {
324 curr,
325 filter,
326 list: self,
327 }
328 }
329}
330
331impl<L, F> Iterator for DrainFilter<'_, L, F>
332where
333 L: Link,
334 F: FnMut(&L::Target) -> bool,
335{
336 type Item = L::Handle;
337
338 fn next(&mut self) -> Option<Self::Item> {
339 while let Some(curr) = self.curr {
340 // safety: the pointer references data contained by the list
341 self.curr = unsafe { L::pointers(curr).as_ref() }.get_next();
342
343 // safety: the value is still owned by the linked list.
344 if (self.filter)(unsafe { &mut *curr.as_ptr() }) {
345 return unsafe { self.list.remove(curr) };
346 }
347 }
348
349 None
350 }
351}
352
353// ===== impl Pointers =====
354
355impl<T> Pointers<T> {
356 /// Create a new set of empty pointers
357 #[must_use]
358 pub const fn new() -> Self {
359 Self {
360 inner: UnsafeCell::new(PointersInner {
361 prev: None,
362 next: None,
363 _pin: PhantomPinned,
364 }),
365 }
366 }
367
368 pub const fn get_prev(&self) -> Option<NonNull<T>> {
369 // SAFETY: Field is accessed immutably through a reference.
370 unsafe { ptr::addr_of!((*self.inner.get()).prev).read() }
371 }
372
373 pub const fn get_next(&self) -> Option<NonNull<T>> {
374 // SAFETY: Field is accessed immutably through a reference.
375 unsafe { ptr::addr_of!((*self.inner.get()).next).read() }
376 }
377
378 pub const fn set_prev(&mut self, value: Option<NonNull<T>>) {
379 // SAFETY: Field is accessed mutably through a mutable reference.
380 unsafe {
381 ptr::addr_of_mut!((*self.inner.get()).prev).write(value);
382 }
383 }
384
385 pub const fn set_next(&mut self, value: Option<NonNull<T>>) {
386 // SAFETY: Field is accessed mutably through a mutable reference.
387 unsafe {
388 ptr::addr_of_mut!((*self.inner.get()).next).write(value);
389 }
390 }
391}
392
393impl<T> fmt::Debug for Pointers<T> {
394 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
395 let prev = self.get_prev();
396 let next = self.get_next();
397 f.debug_struct("Pointers")
398 .field("prev", &prev)
399 .field("next", &next)
400 .finish()
401 }
402}