pin_list/
list.rs

1//! The list itself, and its cursor API.
2
3use crate::id;
4use crate::util::abort;
5use crate::util::debug_unreachable;
6use crate::util::run_on_drop;
7use crate::util::ConstFnBounds;
8use crate::Id;
9use crate::InitializedNode;
10use crate::Node;
11use core::cell::UnsafeCell;
12use core::fmt;
13use core::fmt::Debug;
14use core::fmt::Formatter;
15use core::mem;
16use core::mem::align_of;
17use core::mem::transmute;
18use core::pin::Pin;
19use core::ptr;
20use core::ptr::NonNull;
21
22/// Types used in a [`PinList`]. This trait is used to avoid an excessive number of generic
23/// parameters on [`PinList`] and related types.
24///
25/// Generally you won't want to implement this trait directly — instead you can create ad-hoc
26/// implementations by using `dyn Trait` syntax, for example:
27///
28/// ```
29/// type PinListTypes = dyn pin_list::Types<
30///     Id = pin_list::id::Checked,
31///     Protected = (),
32///     Removed = (),
33///     Unprotected = (),
34/// >;
35/// type PinList = pin_list::PinList<PinListTypes>;
36/// ```
37pub trait Types {
38    /// The ID type this list uses to ensure that different [`PinList`]s are not mixed up.
39    ///
40    /// This crate provides a couple built-in ID types, but you can also define your own:
41    /// - [`id::Checked`]:
42    ///     IDs are allocated with a single global atomic `u64` counter.
43    /// - [`id::Unchecked`]:
44    ///     The responsibility is left up to the user to ensure that different [`PinList`]s are not
45    ///     incorrectly mixed up. Using this is `unsafe`.
46    /// - [`id::DebugChecked`]:
47    ///     Equivalent to [`id::Checked`] when `debug_assertions` are enabled, but
48    ///     [`id::Unchecked`] in release.
49    /// - [`id::Lifetime`]:
50    ///     A fully statically checked ID based on invariant lifetimes and HRTBs — this is the same
51    ///     technique as used by `GhostCell`. While theoretically the best option, its infectious
52    ///     nature makes it not very useful in practice.
53    type Id: Id;
54
55    /// Data owned by each node in the list (before it has been removed) and protected by the list.
56    /// This is only accessible when the list is.
57    ///
58    /// When the node is removed from the list, this value is replaced with [`Removed`].
59    ///
60    /// [`Removed`]: Self::Removed
61    type Protected;
62
63    /// Data owned by each node after it has been removed from the list.
64    type Removed;
65
66    /// Data owned by each node in the list but not protected by the list.
67    ///
68    /// This is always accessible by shared reference from the node itself without accessing the
69    /// list, and is acessible by shared reference from the [`PinList`].
70    type Unprotected;
71}
72
73/// An intrusive linked list.
74pub struct PinList<T: ?Sized + Types> {
75    /// The list's unique ID.
76    pub(crate) id: T::Id,
77
78    /// The head of the list.
79    ///
80    /// If this is `None`, the list is empty.
81    head: OptionNodeShared<T>,
82
83    /// The tail of the list.
84    ///
85    /// Whether this is `None` must remain in sync with whether `head` is `None`.
86    tail: OptionNodeShared<T>,
87}
88
89/// An optional pointer to a `NodeShared`.
90///
91/// Unlike `Option<NonNull<NodeShared<T>>>`, this has a niche.
92pub(crate) struct OptionNodeShared<T: ?Sized + Types>(NonNull<NodeShared<T>>);
93
94impl<T: ?Sized + Types> OptionNodeShared<T> {
95    pub(crate) const NONE: Self = Self(Self::SENTINEL);
96    pub(crate) fn some(ptr: NonNull<NodeShared<T>>) -> Self {
97        Self(ptr)
98    }
99    pub(crate) fn get(self) -> Option<NonNull<NodeShared<T>>> {
100        (self.0 != Self::SENTINEL).then(|| self.0)
101    }
102    const SENTINEL: NonNull<NodeShared<T>> = {
103        // `NodeShared` indirectly contains pointers, so we know this is true.
104        assert!(2 <= align_of::<NodeShared<T>>());
105
106        // We use a value of 1 as the sentinel since it isn’t aligned
107        // and thus can’t be mistaken for a valid value.
108        //
109        // We use a transmute to explicitly polyfill `ptr::without_provenance`.
110        #[allow(clippy::useless_transmute)]
111        unsafe {
112            NonNull::new_unchecked(transmute::<usize, *mut NodeShared<T>>(1))
113        }
114    };
115}
116
117impl<T: ?Sized + Types> Clone for OptionNodeShared<T> {
118    fn clone(&self) -> Self {
119        *self
120    }
121}
122impl<T: ?Sized + Types> Copy for OptionNodeShared<T> {}
123
124/// The state of a node in a list shared between the node's owner and other types.
125///
126/// This type is only accessed by shared reference because there are multiple places that need to
127/// have non-invalidated pointers to it.
128pub(crate) struct NodeShared<T: ?Sized + Types> {
129    /// State of this node that is protected by the `PinList`.
130    pub(crate) protected: UnsafeCell<NodeProtected<T>>,
131
132    /// State of this node not protected by the `PinList`.
133    pub(crate) unprotected: T::Unprotected,
134}
135
136pub(crate) enum NodeProtected<T: ?Sized + Types> {
137    /// The node is present in the list.
138    Linked(NodeLinked<T>),
139
140    /// This node has been removed from the list.
141    Removed(NodeRemoved<T>),
142}
143
144pub(crate) struct NodeLinked<T: ?Sized + Types> {
145    /// The previous node in the linked list.
146    pub(crate) prev: OptionNodeShared<T>,
147
148    /// The next node in the linked list.
149    pub(crate) next: OptionNodeShared<T>,
150
151    /// Any extra data the user wants to store in this state.
152    pub(crate) data: T::Protected,
153}
154
155pub(crate) struct NodeRemoved<T: ?Sized + Types> {
156    /// Any extra data the user wants to store in this state.
157    pub(crate) data: T::Removed,
158}
159
160unsafe impl<T: ?Sized + Types> Send for PinList<T>
161where
162    // Required because it is owned by this type and will be dropped by it.
163    T::Id: Send,
164
165    // (SAFETY) Not required because the ownership of IDs are not shared.
166    /* T::Id: ?Sync, */
167    // Required because we we expose exclusive access to values of this type.
168    T::Protected: Send,
169
170    // (SAFETY) Not required because multiple `&PinList`s on different threads are required to
171    // access this type in a `Sync`-requiring way, which would need `PinList: Sync` (which does
172    // require `T::Protected: Sync`). In other words, `Self: Send` alone only allows exclusive or
173    // reentrant access which is OK by `Send + !Sync`.
174    /* T::Protected: ?Sync, */
175    // Required because ownership can be transferred into the list nodes which may be on a
176    // different thread.
177    T::Removed: Send,
178
179    // (SAFETY) Not required because we never deal in `&T::Removed` — it's always passed by
180    // ownership.
181    /* T::Removed: ?Sync, */
182
183    // (SAFETY) Not required because we don't drop it and we only access it by shared reference.
184    /* T::Unprotected: ?Send, */
185    // Required because values of the type can be shared between this list and its nodes even
186    // without the guard held.
187    T::Unprotected: Sync,
188{
189}
190
191unsafe impl<T: ?Sized + Types> Sync for PinList<T>
192where
193    // (SAFETY) Not required because ownership of IDs can't be obtained from a shared reference.
194    /* T::Id: ?Send, */
195    // Required because ID comparison code uses its `PartialEq` implementation, which accesses it
196    // by shared reference.
197    T::Id: Sync,
198
199    // Both `Send` and `Sync` are required because this value can be accessed by both shared
200    // and exclusive reference from a shared reference to the list.
201    T::Protected: Send + Sync,
202
203    // Required because ownership can be transferred into the list nodes which may be on
204    // a different thread.
205    T::Removed: Send,
206
207    // (SAFETY) Not required because we never deal in `&T::Removed` — it's always passed by
208    // ownership.
209    /* T::Removed: ?Sync, */
210
211    // (SAFETY) Not required because we don't drop it and we only access it by shared reference.
212    /* T::Unprotected: ?Send, */
213    // Required because values of the type can be shared between this list and its nodes.
214    T::Unprotected: Sync,
215{
216}
217
218impl<T: ?Sized> PinList<T>
219where
220    <T as ConstFnBounds>::Type: Types,
221{
222    /// Create a new empty `PinList` from a unique ID.
223    #[must_use]
224    pub const fn new(id: id::Unique<<<T as ConstFnBounds>::Type as Types>::Id>) -> Self {
225        Self {
226            id: id.into_inner(),
227            head: OptionNodeShared::NONE,
228            tail: OptionNodeShared::NONE,
229        }
230    }
231}
232
233impl<T: ?Sized + Types> PinList<T> {
234    /// Check whether there are any nodes in this list.
235    #[must_use]
236    pub fn is_empty(&self) -> bool {
237        debug_assert_eq!(self.head.get().is_some(), self.tail.get().is_some());
238        self.head.get().is_none()
239    }
240
241    /// # Safety
242    ///
243    /// The node must be present in the list.
244    pub(crate) unsafe fn cursor(&self, current: OptionNodeShared<T>) -> Cursor<'_, T> {
245        Cursor {
246            list: self,
247            current,
248        }
249    }
250
251    /// # Safety
252    ///
253    /// - The node must be present in the list.
254    /// - This cursor must not be used to invalidate any other cursors in the list (by e.g.
255    ///   removing nodes out from under them).
256    pub(crate) unsafe fn cursor_mut(&mut self, current: OptionNodeShared<T>) -> CursorMut<'_, T> {
257        CursorMut {
258            list: self,
259            current,
260        }
261    }
262
263    /// Obtain a `Cursor` pointing to the "ghost" element of the list.
264    #[must_use]
265    pub fn cursor_ghost(&self) -> Cursor<'_, T> {
266        // SAFETY: The ghost cursor is always in the list.
267        unsafe { self.cursor(OptionNodeShared::NONE) }
268    }
269
270    /// Obtain a `Cursor` pointing to the first element of the list, or the ghost element if the
271    /// list is empty.
272    #[must_use]
273    pub fn cursor_front(&self) -> Cursor<'_, T> {
274        let mut cursor = self.cursor_ghost();
275        cursor.move_next();
276        cursor
277    }
278
279    /// Obtain a `Cursor` pointing to the last element of the list, or the ghost element if the
280    /// list is empty.
281    #[must_use]
282    pub fn cursor_back(&self) -> Cursor<'_, T> {
283        let mut cursor = self.cursor_ghost();
284        cursor.move_previous();
285        cursor
286    }
287
288    /// Obtain a `CursorMut` pointing to the "ghost" element of the list.
289    #[must_use]
290    pub fn cursor_ghost_mut(&mut self) -> CursorMut<'_, T> {
291        // SAFETY: The ghost cursor is always in the list, and the `&mut Self` ensures that safe
292        // code cannot currently hold a cursor.
293        unsafe { self.cursor_mut(OptionNodeShared::NONE) }
294    }
295
296    /// Obtain a `CursorMut` pointing to the first element of the list, or the ghost element if the
297    /// list is empty.
298    #[must_use]
299    pub fn cursor_front_mut(&mut self) -> CursorMut<'_, T> {
300        let mut cursor = self.cursor_ghost_mut();
301        cursor.move_next();
302        cursor
303    }
304
305    /// Obtain a `CursorMut` pointing to the last element of the list, or the ghost element if the
306    /// list is empty.
307    #[must_use]
308    pub fn cursor_back_mut(&mut self) -> CursorMut<'_, T> {
309        let mut cursor = self.cursor_ghost_mut();
310        cursor.move_previous();
311        cursor
312    }
313
314    /// Append a node to the front of the list.
315    ///
316    /// # Panics
317    ///
318    /// Panics if the node is not in its initial state.
319    pub fn push_front<'node>(
320        &mut self,
321        node: Pin<&'node mut Node<T>>,
322        protected: T::Protected,
323        unprotected: T::Unprotected,
324    ) -> Pin<&'node mut InitializedNode<'node, T>> {
325        self.cursor_ghost_mut()
326            .insert_after(node, protected, unprotected)
327    }
328
329    /// Append a node to the back of the list.
330    ///
331    /// # Panics
332    ///
333    /// Panics if the node is not in its initial state.
334    pub fn push_back<'node>(
335        &mut self,
336        node: Pin<&'node mut Node<T>>,
337        protected: T::Protected,
338        unprotected: T::Unprotected,
339    ) -> Pin<&'node mut InitializedNode<'node, T>> {
340        self.cursor_ghost_mut()
341            .insert_before(node, protected, unprotected)
342    }
343}
344
345#[allow(clippy::missing_fields_in_debug)]
346impl<T: ?Sized + Types> Debug for PinList<T> {
347    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
348        f.debug_struct("PinList").field("id", &self.id).finish()
349    }
350}
351
352/// A shared cursor into a linked list.
353///
354/// This can be created by methods like [`PinList::cursor_ghost`].
355///
356/// Each cursor conceptually points to a single item in the list. It can also point to the space
357/// between the start and end of the list, in which case it is called the ghost cursor.
358///
359/// This type is not `Copy` to prevent accidental copies, but its `Clone` implementation is just a
360/// bitwise copy — very cheap.
361pub struct Cursor<'list, T: ?Sized + Types> {
362    list: &'list PinList<T>,
363    current: OptionNodeShared<T>,
364}
365
366unsafe impl<T: ?Sized + Types> Send for Cursor<'_, T> where
367    // (SAFETY) Required because we hold a shared reference to a `PinList`.
368    PinList<T>: Sync
369{
370}
371
372unsafe impl<T: ?Sized + Types> Sync for Cursor<'_, T> where
373    // (SAFETY) Required because we hold a shared reference to a `PinList`.
374    PinList<T>: Sync
375{
376}
377
378impl<'list, T: ?Sized + Types> Cursor<'list, T> {
379    fn current_shared(&self) -> Option<&'list NodeShared<T>> {
380        // SAFETY: A cursor always points to a valid node in the list (ensured by
381        // `PinList::cursor`).
382        self.current
383            .get()
384            .map(|current| unsafe { current.as_ref() })
385    }
386    fn current_protected(&self) -> Option<&'list NodeProtected<T>> {
387        // SAFETY: Our shared reference to the list gives us shared access to the protected data of
388        // every node in it.
389        Some(unsafe { &*self.current_shared()?.protected.get() })
390    }
391    fn current_linked(&self) -> Option<&'list NodeLinked<T>> {
392        match self.current_protected()? {
393            NodeProtected::Linked(linked) => Some(linked),
394            NodeProtected::Removed(..) => unsafe { debug_unreachable!() },
395        }
396    }
397
398    /// Move the cursor to the next element in the linked list.
399    pub fn move_next(&mut self) {
400        self.current = match self.current_linked() {
401            Some(linked) => linked.next,
402            None => self.list.head,
403        };
404    }
405
406    /// Move the cursor to the previous element in the linked list.
407    pub fn move_previous(&mut self) {
408        self.current = match self.current_linked() {
409            Some(linked) => linked.prev,
410            None => self.list.tail,
411        };
412    }
413
414    /// Retrieve a shared reference to the list this cursor uses.
415    #[must_use]
416    pub fn list(&self) -> &'list PinList<T> {
417        self.list
418    }
419
420    /// Retrieve a shared reference to the protected data of this linked list node.
421    ///
422    /// Returns [`None`] if the cursor is the ghost cursor.
423    #[must_use]
424    pub fn protected(&self) -> Option<&'list T::Protected> {
425        Some(&self.current_linked()?.data)
426    }
427
428    /// Retrieve a shared reference to the unprotected data of this linked list node.
429    ///
430    /// Returns [`None`] if the cursor is the ghost cursor.
431    #[must_use]
432    pub fn unprotected(&self) -> Option<&'list T::Unprotected> {
433        Some(&self.current_shared()?.unprotected)
434    }
435}
436
437impl<T: ?Sized + Types> Clone for Cursor<'_, T> {
438    fn clone(&self) -> Self {
439        Self {
440            list: self.list,
441            current: self.current,
442        }
443    }
444}
445
446impl<T: ?Sized + Types> Debug for Cursor<'_, T>
447where
448    T::Unprotected: Debug,
449    T::Protected: Debug,
450{
451    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
452        f.debug_struct("Cursor")
453            .field("list", &self.list)
454            .field("protected", &self.protected())
455            .field("unprotected", &self.unprotected())
456            .finish()
457    }
458}
459
460/// A unique cursor into a linked list.
461///
462/// This can be created by methods like [`PinList::cursor_ghost_mut`].
463///
464/// Each cursor conceptually points to a single item in the list. It can also point to the space
465/// between the start and end of the list, in which case it is called the ghost cursor.
466pub struct CursorMut<'list, T: ?Sized + Types> {
467    pub(crate) list: &'list mut PinList<T>,
468    pub(crate) current: OptionNodeShared<T>,
469}
470
471unsafe impl<T: ?Sized + Types> Send for CursorMut<'_, T> where
472    // (SAFETY) Required because we hold a unique reference to a `PinList`.
473    PinList<T>: Send
474{
475}
476
477unsafe impl<T: ?Sized + Types> Sync for CursorMut<'_, T> where
478    // (SAFETY) Required because we hold a unique reference to a `PinList`.
479    PinList<T>: Sync
480{
481}
482
483impl<'list, T: ?Sized + Types> CursorMut<'list, T> {
484    fn current_shared(&self) -> Option<&NodeShared<T>> {
485        // SAFETY: A cursor always points to a valid node in the list (ensured by
486        // `PinList::cursor_mut`).
487        self.current
488            .get()
489            .map(|current| unsafe { current.as_ref() })
490    }
491    fn current_protected(&self) -> Option<&NodeProtected<T>> {
492        // SAFETY: Our shared reference to the list gives us shared access to the protected data of
493        // every node in it.
494        Some(unsafe { &*self.current_shared()?.protected.get() })
495    }
496    fn current_protected_mut(&mut self) -> Option<&mut NodeProtected<T>> {
497        // SAFETY: Our unique reference to the list gives us unique access to the protected data of
498        // every node in it.
499        Some(unsafe { &mut *self.current_shared()?.protected.get() })
500    }
501    fn current_linked(&self) -> Option<&NodeLinked<T>> {
502        match self.current_protected()? {
503            NodeProtected::Linked(linked) => Some(linked),
504            NodeProtected::Removed(..) => unsafe { debug_unreachable!() },
505        }
506    }
507    fn current_linked_mut(&mut self) -> Option<&mut NodeLinked<T>> {
508        match self.current_protected_mut()? {
509            NodeProtected::Linked(linked) => Some(linked),
510            NodeProtected::Removed(..) => unsafe { debug_unreachable!() },
511        }
512    }
513    pub(crate) fn prev_mut(&mut self) -> &mut OptionNodeShared<T> {
514        match self.current.get() {
515            // Unwrap because we don't have polonius
516            Some(_) => &mut self.current_linked_mut().unwrap().prev,
517            None => &mut self.list.tail,
518        }
519    }
520    pub(crate) fn next_mut(&mut self) -> &mut OptionNodeShared<T> {
521        match self.current.get() {
522            // Unwrap because we don't have polonius
523            Some(_) => &mut self.current_linked_mut().unwrap().next,
524            None => &mut self.list.head,
525        }
526    }
527
528    /// Downgrade this cursor to its shared form.
529    #[must_use]
530    pub fn into_shared(self) -> Cursor<'list, T> {
531        Cursor {
532            list: self.list,
533            current: self.current,
534        }
535    }
536
537    /// Reborrow this cursor as its shared form.
538    ///
539    /// Note that reborrowing this cursor as another `CursorMut` is disallowed because it would
540    /// allow invalidating this cursor while it still exists.
541    #[must_use]
542    pub fn as_shared(&self) -> Cursor<'_, T> {
543        Cursor {
544            list: self.list,
545            current: self.current,
546        }
547    }
548
549    /// Move the cursor to the next element in the linked list.
550    pub fn move_next(&mut self) {
551        self.current = *self.next_mut();
552    }
553
554    /// Move the cursor to the previous element in the linked list.
555    pub fn move_previous(&mut self) {
556        self.current = *self.prev_mut();
557    }
558
559    /// Retrieve a shared reference to the list this cursor uses.
560    #[must_use]
561    pub fn list(&self) -> &PinList<T> {
562        self.list
563    }
564
565    /// Retrieve a shared reference to the protected data of this linked list node.
566    ///
567    /// Returns [`None`] if the cursor is currently the ghost cursor.
568    #[must_use]
569    pub fn protected(&self) -> Option<&T::Protected> {
570        Some(&self.current_linked()?.data)
571    }
572
573    /// Retrieve a unique reference to the protected data of this linked list node.
574    ///
575    /// Returns [`None`] if the cursor is currently the ghost cursor.
576    #[must_use]
577    pub fn protected_mut(&mut self) -> Option<&mut T::Protected> {
578        Some(&mut self.current_linked_mut()?.data)
579    }
580
581    /// Retrieve a shared reference to the unprotected data of this linked list node.
582    ///
583    /// Returns [`None`] if the cursor is currently the ghost cursor.
584    #[must_use]
585    pub fn unprotected(&self) -> Option<&T::Unprotected> {
586        Some(&self.current_shared()?.unprotected)
587    }
588
589    /// Insert a node into the linked list before this one.
590    ///
591    /// # Panics
592    ///
593    /// Panics if the node is not in its initial state.
594    pub fn insert_before<'node>(
595        &mut self,
596        node: Pin<&'node mut Node<T>>,
597        protected: T::Protected,
598        unprotected: T::Unprotected,
599    ) -> Pin<&'node mut InitializedNode<'node, T>> {
600        node.insert_before(self, protected, unprotected)
601    }
602
603    /// Insert a node into the linked list after this one.
604    ///
605    /// # Panics
606    ///
607    /// Panics if the node is not in its initial state.
608    pub fn insert_after<'node>(
609        &mut self,
610        node: Pin<&'node mut Node<T>>,
611        protected: T::Protected,
612        unprotected: T::Unprotected,
613    ) -> Pin<&'node mut InitializedNode<'node, T>> {
614        node.insert_after(self, protected, unprotected)
615    }
616
617    /// Append a node to the front of the list.
618    ///
619    /// # Panics
620    ///
621    /// Panics if the node is not in its initial state.
622    pub fn push_front<'node>(
623        &mut self,
624        node: Pin<&'node mut Node<T>>,
625        protected: T::Protected,
626        unprotected: T::Unprotected,
627    ) -> Pin<&'node mut InitializedNode<'node, T>> {
628        self.list.push_front(node, protected, unprotected)
629    }
630
631    /// Append a node to the back of the list.
632    ///
633    /// # Panics
634    ///
635    /// Panics if the node is not in its initial state.
636    pub fn push_back<'node>(
637        &mut self,
638        node: Pin<&'node mut Node<T>>,
639        protected: T::Protected,
640        unprotected: T::Unprotected,
641    ) -> Pin<&'node mut InitializedNode<'node, T>> {
642        self.list.push_back(node, protected, unprotected)
643    }
644
645    /// Remove this node from the linked list with a given "removed" value.
646    ///
647    /// The cursor is moved to point to the next element in the linked list.
648    ///
649    /// # Errors
650    ///
651    /// Fails if the cursor is currently the ghost cursor (not over an item).
652    pub fn remove_current(&mut self, removed: T::Removed) -> Result<T::Protected, T::Removed> {
653        let mut res = Err(removed);
654        self.remove_current_with(|protected| match mem::replace(&mut res, Ok(protected)) {
655            Ok(..) => unsafe { debug_unreachable!() },
656            Err(removed) => removed,
657        });
658        res
659    }
660
661    /// Remove this node from the linked list, computing its "removed" value from a closure.
662    ///
663    /// The cursor is moved to point to the next element in the linked list.
664    ///
665    /// If the given closure panics, the process will abort.
666    ///
667    /// Returns whether the operation was successful — it fails if the cursor is currently a ghost
668    /// cursor (not over an item).
669    pub fn remove_current_with<F>(&mut self, f: F) -> bool
670    where
671        F: FnOnce(T::Protected) -> T::Removed,
672    {
673        self.remove_current_with_or(f, || abort())
674    }
675
676    /// Remove this node from the linked list, computing its "removed" value from a closure, or
677    /// using a secondary closure should the first panic. If the secondary closure panics, the
678    /// process will abort.
679    ///
680    /// The cursor is moved to point to the next element in the linked list.
681    ///
682    /// Returns whether the operation was successful — it fails if the cursor is currently a ghost
683    /// cursor (not over an item).
684    pub fn remove_current_with_or<F, Fallback>(&mut self, f: F, fallback: Fallback) -> bool
685    where
686        F: FnOnce(T::Protected) -> T::Removed,
687        Fallback: FnOnce() -> T::Removed,
688    {
689        let protected: *mut NodeProtected<T> = match self.current_protected_mut() {
690            Some(protected) => protected,
691            None => return false,
692        };
693
694        // Take the protected data so we can do things to it.
695        // SAFETY: Control flow cannot exit this function until a value is placed into `protected`
696        // by `ptr::write`.
697        let old = match unsafe { ptr::read(protected) } {
698            NodeProtected::Linked(linked) => linked,
699            NodeProtected::Removed(..) => unsafe { debug_unreachable!() },
700        };
701
702        // Remove ourselves from the list.
703        *unsafe { self.list.cursor_mut(old.prev) }.next_mut() = old.next;
704        *unsafe { self.list.cursor_mut(old.next) }.prev_mut() = old.prev;
705
706        // Move the cursor to the next element in the list
707        self.current = old.next;
708
709        // This guard makes sure to always set the current node's state to removed even if `f`
710        // panics.
711        let guard = run_on_drop(|| {
712            // Since this only runs when the thread is already panicking, `fallback()` panicking
713            // results in a double-panic which leads to an abort.
714            let removed = NodeRemoved { data: fallback() };
715            unsafe { ptr::write(protected, NodeProtected::Removed(removed)) };
716        });
717
718        // Calculate the new user data and set the state to to removed.
719        let removed = NodeRemoved { data: f(old.data) };
720        unsafe { ptr::write(protected, NodeProtected::Removed(removed)) };
721
722        // Disarm the guard now that `protected` holds a valid value again.
723        mem::forget(guard);
724
725        true
726    }
727}
728
729impl<T: ?Sized + Types> Debug for CursorMut<'_, T>
730where
731    T::Unprotected: Debug,
732    T::Protected: Debug,
733{
734    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
735        f.debug_struct("CursorMut")
736            .field("list", &self.list)
737            .field("protected", &self.protected())
738            .field("unprotected", &self.unprotected())
739            .finish()
740    }
741}