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}