rustpython_common/
linked_list.rs

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