pin_list/
node.rs

1//! The `Node` type and its related APIs.
2
3use crate::list::NodeLinked;
4use crate::list::NodeProtected;
5use crate::list::NodeRemoved;
6use crate::list::NodeShared;
7use crate::list::OptionNodeShared;
8use crate::util::abort;
9use crate::util::debug_unreachable;
10use crate::util::unwrap_unchecked;
11use crate::util::ConstFnBounds;
12use crate::Cursor;
13use crate::CursorMut;
14use crate::PinList;
15use crate::Types;
16use core::cell::UnsafeCell;
17use core::fmt;
18use core::fmt::Debug;
19use core::fmt::Formatter;
20use core::marker::PhantomData;
21use core::mem;
22use core::ops::Deref;
23use core::pin::Pin;
24use core::ptr::NonNull;
25use pin_project_lite::pin_project;
26use pinned_aliasable::Aliasable;
27
28pin_project! {
29    /// A node in a [`PinList`].
30    ///
31    /// This type is a state machine between three states:
32    /// 1. **Initial:**
33    ///     The initial state; the node is not registered in any list. This is the only state that
34    ///     can be dropped without aborting the process.
35    /// 2. **Linked:**
36    ///     The node has been linked into a [`PinList`]. It holds a `Protected` and an
37    ///     `Unprotected`, of which the former can only be accessed when access to the [`PinList`]
38    ///     can be proven. Dropping a node in this state will abort.
39    /// 3. **Removed:**
40    ///     The node has been removed from a [`PinList`]. It holds a `Removed` and an
41    ///     `Unprotected`. Similar to the "linked" state, proof of access to the [`PinList`] is
42    ///     required for most operations. Dropping a node in this state will abort.
43    pub struct Node<T>
44    where
45        T: ?Sized,
46        T: Types,
47    {
48        // `None` if initial, `Some` if initialized
49        #[pin]
50        inner: Option<NodeInner<T>>,
51    }
52
53    impl<T> PinnedDrop for Node<T>
54    where
55        T: ?Sized,
56        T: Types,
57    {
58        fn drop(this: Pin<&mut Self>) {
59            // If we might be linked into a list at this point in time, we have no choice but to
60            // abort in order to preserve soundness and prevent use-after-frees.
61            if this.inner.is_some() {
62                abort();
63            }
64        }
65    }
66}
67
68pin_project! {
69    struct NodeInner<T>
70    where
71        T: ?Sized,
72        T: Types,
73    {
74        // The ID of the list this node is/was registered in, used for checking whether access to
75        // the inner state is valid.
76        list_id: T::Id,
77
78        // State that is also accessible by a walker of the list (cursors).
79        #[pin]
80        shared: Aliasable<NodeShared<T>>,
81    }
82}
83
84unsafe impl<T: ?Sized + Types> Send for Node<T>
85where
86    // Required because it is owned by this type and will be dropped by it.
87    T::Id: Send,
88
89    // (SAFETY) Not required because the ownership of IDs are not shared.
90    /* T::Id: ?Sync, */
91    // Required because we can take and return instances of this type by value.
92    T::Protected: Send,
93
94    // (SAFETY) Not required because multiple `&PinList`s on different threads are required to
95    // access this type in a `Sync`-requiring way, which would need `PinList: Sync` (which does
96    // require `T::Protected: Sync`). In other words, `Self: Send` alone only allows exclusive or
97    // reentrant access which is OK by `Send + !Sync`.
98    /* T::Protected: ?Sync, */
99    // Required because we can take and return this type by value.
100    T::Removed: Send,
101
102    // (SAFETY) Not required because we never deal in `&T::Removed` — it's always passed by
103    // ownership.
104    /* T::Removed: ?Sync, */
105    // Required because we can take and return this type by value.
106    T::Unprotected: Send,
107
108    // Required because values of this type can be shared between this node and its list.
109    T::Unprotected: Sync,
110{
111}
112
113unsafe impl<T: ?Sized + Types> Sync for Node<T>
114where
115    // (SAFETY) Not required because ownership of IDs can't be obtained from a shared reference.
116    /* T::Id: ?Send, */
117    // Required because ID comparison code uses its `PartialEq` implementation, which accesses it
118    // by shared reference.
119    T::Id: Sync,
120
121    // (SAFETY) Not required to be `Send` or `Sync` because the only methods that access it that
122    // take `&self` would require the `PinList` to be `Sync` to be called on two threads, which it
123    // isn't if `T::Protected: !Send` or `T::Protected: !Sync`.
124    /* T::Protected: ?Send + ?Sync, */
125
126    // (SAFETY) Not required because ownership of this type is only passed around when a
127    // `Pin<&mut Node<T>>` is the receiver.
128    /* T::Removed: ?Send, */
129
130    // (SAFETY) Not required because we never deal in `&T::Removed` — it's always passed by
131    // ownership.
132    /* T::Removed: ?Sync, */
133
134    // (SAFETY) Not required because ownership of this type is only passed around when a
135    // `Pin<&mut Node<T>` is the receiver.
136    /* T::Unprotected: ?Send, */
137    // Required because shared references to values of this type can be accessed from a shared
138    // reference to the node.
139    T::Unprotected: Sync,
140{
141}
142
143impl<T: ?Sized> Node<T>
144where
145    <T as ConstFnBounds>::Type: Types,
146{
147    /// Create a new node in its initial state.
148    ///
149    /// You can move this node into other states by functions like [`PinList::push_front`].
150    #[must_use]
151    pub const fn new() -> Self {
152        Self { inner: None }
153    }
154}
155
156impl<T: ?Sized + Types> Default for Node<T> {
157    fn default() -> Self {
158        Self::new()
159    }
160}
161
162impl<T: ?Sized + Types> Node<T> {
163    /// Check whether the node is in its initial state.
164    #[must_use]
165    pub fn is_initial(&self) -> bool {
166        self.inner.is_none()
167    }
168
169    /// Insert this node into the linked list before the given cursor.
170    ///
171    /// # Panics
172    ///
173    /// Panics if the node is not in its initial state.
174    pub fn insert_before(
175        self: Pin<&mut Self>,
176        cursor: &mut CursorMut<'_, T>,
177        protected: T::Protected,
178        unprotected: T::Unprotected,
179    ) -> Pin<&mut InitializedNode<'_, T>> {
180        let prev = *cursor.prev_mut();
181
182        // Store our own state as linked.
183        let node = self.init(NodeInner {
184            list_id: cursor.list().id,
185            shared: Aliasable::new(NodeShared {
186                protected: UnsafeCell::new(NodeProtected::Linked(NodeLinked {
187                    prev,
188                    next: cursor.current,
189                    data: protected,
190                })),
191                unprotected,
192            }),
193        });
194
195        // Update the previous node's `next` pointer and the next node's `prev` pointer to both
196        // point to us.
197        *unsafe { cursor.list.cursor_mut(prev) }.next_mut() =
198            OptionNodeShared::some(node.shared_ptr());
199        *cursor.prev_mut() = OptionNodeShared::some(node.shared_ptr());
200
201        node
202    }
203
204    /// Insert this node into the linked list after the given cursor.
205    ///
206    /// # Panics
207    ///
208    /// Panics if the node is not in its initial state.
209    pub fn insert_after(
210        self: Pin<&mut Self>,
211        cursor: &mut CursorMut<'_, T>,
212        protected: T::Protected,
213        unprotected: T::Unprotected,
214    ) -> Pin<&mut InitializedNode<'_, T>> {
215        let next = *cursor.next_mut();
216
217        // Store our own state as linked.
218        let node = self.init(NodeInner {
219            list_id: cursor.list().id,
220            shared: Aliasable::new(NodeShared {
221                protected: UnsafeCell::new(NodeProtected::Linked(NodeLinked {
222                    prev: cursor.current,
223                    next,
224                    data: protected,
225                })),
226                unprotected,
227            }),
228        });
229
230        // Update the previous node's `next` pointer and the next node's `prev` pointer to both
231        // point to us.
232        *cursor.next_mut() = OptionNodeShared::some(node.shared_ptr());
233        *unsafe { cursor.list.cursor_mut(next) }.prev_mut() =
234            OptionNodeShared::some(node.shared_ptr());
235
236        node
237    }
238
239    fn init(mut self: Pin<&mut Self>, new_inner: NodeInner<T>) -> Pin<&mut InitializedNode<'_, T>> {
240        let mut inner = self.as_mut().project().inner;
241
242        assert!(inner.is_none(), "attempted to link an already-linked node");
243
244        inner.set(Some(new_inner));
245
246        // SAFETY: We just set the inner to `Some`.
247        unsafe { InitializedNode::new_mut_unchecked(self) }
248    }
249
250    /// Borrow the node, if it is initialized (linked or removed).
251    ///
252    /// Returns [`None`] if the node is in the initial state.
253    #[must_use]
254    pub fn initialized(&self) -> Option<&InitializedNode<'_, T>> {
255        InitializedNode::new_ref(self)
256    }
257
258    /// Borrow uniquely the node, if it is initialized (linked or removed).
259    ///
260    /// Returns [`None`] if the node is in the initial state.
261    #[must_use]
262    pub fn initialized_mut(self: Pin<&mut Self>) -> Option<Pin<&mut InitializedNode<'_, T>>> {
263        InitializedNode::new_mut(self)
264    }
265}
266
267impl<T: ?Sized + Types> Debug for Node<T>
268where
269    T::Unprotected: Debug,
270{
271    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
272        if let Some(initialized) = &self.initialized() {
273            f.debug_struct("Node::Initialized")
274                .field("list_id", &initialized.inner().list_id)
275                .field("unprotected", initialized.unprotected())
276                .finish()
277        } else {
278            f.pad("Node::Initial")
279        }
280    }
281}
282
283/// A [`Node`] which is guaranteed to be initialized, accessed by [`Node::initialized`] and
284/// [`Node::initialized_mut`].
285///
286/// You can never create and will never interact with owned or `&mut` instances of this type — it
287/// is accessed solely as `&InitializedNode<'_, T>` or `Pin<&mut InitializedNode<'_, T>>`.
288#[repr(transparent)]
289pub struct InitializedNode<'node, T: ?Sized + Types> {
290    // Hold a `Node<T>` and not a `NodeInner<T>` so we can set its value to `None`.
291    node: Node<T>,
292    // This `'node` lifetime is used to allow "owned references" to the `InitializedNode`:
293    // `Pin<&'node mut InitializedNode<'node, T>>`. Because the unique reference makes the `'node`
294    // lifetime invariant, such a type enforces that the reference is not used after that call.
295    _lifetime: PhantomData<&'node ()>,
296}
297
298impl<T: ?Sized + Types> Deref for InitializedNode<'_, T> {
299    type Target = Node<T>;
300    fn deref(&self) -> &Self::Target {
301        &self.node
302    }
303}
304
305impl<'node, T: ?Sized + Types> InitializedNode<'node, T> {
306    fn new_ref(node: &'node Node<T>) -> Option<&'node Self> {
307        node.inner.as_ref()?;
308        // SAFETY: We have just asserted that `inner` is `Some` and we are `#[repr(transparent)]`
309        // over `Node<T>`.
310        Some(unsafe { mem::transmute::<&'node Node<T>, &'node InitializedNode<'node, T>>(node) })
311    }
312
313    fn new_mut(node: Pin<&'node mut Node<T>>) -> Option<Pin<&'node mut Self>> {
314        node.inner.as_ref()?;
315        // SAFETY: We have just asserted that `inner` is `Some`.
316        Some(unsafe { Self::new_mut_unchecked(node) })
317    }
318
319    unsafe fn new_mut_unchecked(node: Pin<&'node mut Node<T>>) -> Pin<&'node mut Self> {
320        // SAFETY: Caller ensures that `inner` is `Some`, and we are `#[repr(transparent)]`
321        // over `Node<T>`.
322        unsafe {
323            mem::transmute::<Pin<&'node mut Node<T>>, Pin<&'node mut InitializedNode<'node, T>>>(
324                node,
325            )
326        }
327    }
328
329    fn inner(&self) -> Pin<&NodeInner<T>> {
330        // SAFETY: In order for this type to exist, the node must be initialized.
331        let inner = unsafe { unwrap_unchecked(self.node.inner.as_ref()) };
332
333        // SAFETY: In order for this state to be created, we must already have been pinned.
334        unsafe { Pin::new_unchecked(inner) }
335    }
336
337    fn shared(&self) -> &NodeShared<T> {
338        self.inner().project_ref().shared.get()
339    }
340
341    fn shared_ptr(&self) -> NonNull<NodeShared<T>> {
342        NonNull::from(self.shared())
343    }
344
345    /// Get a shared reference to the unprotected data of this node.
346    #[must_use]
347    pub fn unprotected(&self) -> &T::Unprotected {
348        &self.shared().unprotected
349    }
350
351    /// Get a shared reference to the protected data of this node.
352    ///
353    /// Returns [`None`] if the node is in its removed state (has been removed from the list).
354    ///
355    /// # Panics
356    ///
357    /// Panics if the given list is a different one than this node was registered with.
358    #[must_use]
359    pub fn protected<'list>(&self, list: &'list PinList<T>) -> Option<&'list T::Protected> {
360        assert_eq!(self.inner().list_id, list.id, "incorrect `PinList`");
361
362        // SAFETY: We have shared access to both `self` and our `PinList`, as guaranteed above.
363        match unsafe { &*self.shared().protected.get() } {
364            NodeProtected::Linked(linked) => Some(&linked.data),
365            NodeProtected::Removed(..) => None,
366        }
367    }
368
369    /// Get a unique reference to the protected data of this node.
370    ///
371    /// Returns [`None`] if the node is in its removed state (has been removed from the list).
372    ///
373    /// # Panics
374    ///
375    /// Panics if the given list is a different one than this node was registered with.
376    #[must_use]
377    pub fn protected_mut<'list>(
378        &self,
379        list: &'list mut PinList<T>,
380    ) -> Option<&'list mut T::Protected> {
381        assert_eq!(self.inner().list_id, list.id, "incorrect `PinList`");
382
383        // Only create a shared reference because we only have a shared reference to `self`. In the
384        // `Linked` branch this doesn't end up mattering, but in the `Removed` branch it's possible
385        // that a `&NodeRemoved` existed at the time of calling this function.
386        match unsafe { &*self.shared().protected.get() } {
387            NodeProtected::Linked(..) => {
388                // SAFETY: We have unique access to the list, and we have asserted that the node
389                // isn't removed.
390                Some(match unsafe { &mut *self.shared().protected.get() } {
391                    NodeProtected::Linked(linked) => &mut linked.data,
392                    NodeProtected::Removed(..) => unsafe { debug_unreachable!() },
393                })
394            }
395            NodeProtected::Removed(..) => None,
396        }
397    }
398
399    /// Obtain a shared cursor pointing to this node.
400    ///
401    /// Returns [`None`] if the node was in its removed state (it was removed from the list).
402    ///
403    /// # Panics
404    ///
405    /// Panics if the given list is a different one than this node was registered with.
406    #[must_use]
407    pub fn cursor<'list>(&self, list: &'list PinList<T>) -> Option<Cursor<'list, T>> {
408        assert_eq!(self.inner().list_id, list.id, "incorrect `PinList`");
409
410        // SAFETY: We have shared access to both this node and the list.
411        match unsafe { &*self.shared().protected.get() } {
412            NodeProtected::Linked(..) => {}
413            NodeProtected::Removed(..) => return None,
414        }
415
416        // SAFETY: We have shared access to the list, and this node is not removed from the list.
417        Some(unsafe { list.cursor(OptionNodeShared::some(self.shared_ptr())) })
418    }
419
420    /// Obtain a unique cursor pointing to this node.
421    ///
422    /// Returns [`None`] if the node was in its removed state (it was removed from the list).
423    ///
424    /// # Panics
425    ///
426    /// Panics if the given list is a different one than this node was registered with.
427    #[must_use]
428    pub fn cursor_mut<'list>(&self, list: &'list mut PinList<T>) -> Option<CursorMut<'list, T>> {
429        assert_eq!(self.inner().list_id, list.id, "incorrect `PinList`");
430
431        // Only create a shared reference because we only have a shared reference to `self`. In the
432        // `Linked` branch this doesn't end up mattering, but in the `Removed` branch it's possible
433        // that a `&NodeRemoved` existed at the time of calling this function.
434        match unsafe { &*self.shared().protected.get() } {
435            NodeProtected::Linked(..) => {}
436            NodeProtected::Removed(..) => return None,
437        }
438
439        // SAFETY: We have exclusive access to the list, and this node is not removed from the
440        // list.
441        Some(unsafe { list.cursor_mut(OptionNodeShared::some(self.shared_ptr())) })
442    }
443
444    /// Remove this node from its containing list and take its data, leaving the node in its
445    /// initial state.
446    ///
447    /// # Errors
448    ///
449    /// Fails if the node is in its removed state — use [`take_removed`](Self::take_removed) to
450    /// handle that case, or call [`reset`](Self::reset) instead.
451    ///
452    /// # Panics
453    ///
454    /// Panics if the given list is a different one than this node was registered with.
455    // Take `&'node mut Self` instead of `&mut Self` to ensure that this reference is not used
456    // after this point.
457    pub fn unlink(
458        self: Pin<&'node mut Self>,
459        list: &mut PinList<T>,
460    ) -> Result<(T::Protected, T::Unprotected), Pin<&'node mut Self>> {
461        assert_eq!(self.inner().list_id, list.id, "incorrect `PinList`");
462
463        // SAFETY: We have exclusive access to both the node and the list.
464        let linked = match unsafe { &mut *self.shared().protected.get() } {
465            NodeProtected::Linked(linked) => linked,
466            NodeProtected::Removed(..) => return Err(self),
467        };
468
469        // Link up the nodes around us to remove ourselves from the list.
470        *unsafe { list.cursor_mut(linked.prev) }.next_mut() = linked.next;
471        *unsafe { list.cursor_mut(linked.next) }.prev_mut() = linked.prev;
472
473        // SAFETY: We just unlinked ourselves from the list.
474        match unsafe { self.take_unchecked() } {
475            (NodeData::Linked(linked), unprotected) => Ok((linked, unprotected)),
476            // SAFETY: We asserted at the beginning of this function that we were in the linked
477            // state.
478            (NodeData::Removed(_), _) => unsafe { debug_unreachable!() },
479        }
480    }
481
482    /// Take the data out of this node if it has been removed from the list, leaving the node in
483    /// its initial state.
484    ///
485    /// # Errors
486    ///
487    /// Errors if the node was in its "linked" state (it was still part of the list) — use
488    /// [`unlink`](Self::unlink) in this case, or call [`reset`](Self::reset) instead.
489    ///
490    /// # Panics
491    ///
492    /// Panics if the given list is a different one than this node was registered with.
493    // Take `&'node mut Self` instead of `&mut Self` to ensure that this reference is not used
494    // after this point.
495    pub fn take_removed(
496        self: Pin<&'node mut Self>,
497        list: &PinList<T>,
498    ) -> Result<(T::Removed, T::Unprotected), Pin<&'node mut Self>> {
499        assert_eq!(self.inner().list_id, list.id, "incorrect `PinList`");
500
501        // Only create a shared reference because we only have shared access to the `PinList`. In
502        // the `Removed` branch this doesn't end up mattering, but in the `Linked` branch it's
503        // possible a `&T::Unprotected` existed at the time of calling this function.
504        match unsafe { &*self.shared().protected.get() } {
505            NodeProtected::Removed(..) => {}
506            NodeProtected::Linked(..) => return Err(self),
507        }
508
509        // SAFETY: We just asserted that we are in the removed state.
510        Ok(unsafe { self.take_removed_unchecked() })
511    }
512
513    /// Take the data out of this node, assuming that it has been removed from the list, leaving
514    /// the node in its initial state.
515    ///
516    /// In contrast to [`take_removed`](Self::take_removed), this does not require access to the
517    /// [`PinList`].
518    ///
519    /// # Safety
520    ///
521    /// The node must not be in its linked state.
522    #[must_use]
523    // Take `&'node mut Self` instead of `&mut Self` to ensure that this reference is not used
524    // after this point.
525    pub unsafe fn take_removed_unchecked(
526        self: Pin<&'node mut Self>,
527    ) -> (T::Removed, T::Unprotected) {
528        // SAFETY: Ensured by caller.
529        match unsafe { self.take_unchecked() } {
530            (NodeData::Linked(_), _) => {
531                // oops! the caller has violated the safety invariants of this function. we may
532                // have even already caused UB in `take_unchecked`.
533                // SAFETY: Ensured by caller.
534                unsafe {
535                    debug_unreachable!(
536                        "called `take_remove_unchecked` on a linked node: this is Undefined Behaviour"
537                    )
538                }
539            }
540            (NodeData::Removed(removed), unprotected) => (removed, unprotected),
541        }
542    }
543
544    /// Take the inner data from this node, leaving it in the initial state.
545    ///
546    /// # Safety
547    ///
548    /// The node must have been removed from the list. It can be in either of the `Removed` and
549    /// `Linked` states.
550    // Take `&'node mut Self` instead of `&mut Self` to ensure that this reference is not used
551    // after this point.
552    unsafe fn take_unchecked(self: Pin<&'node mut Self>) -> (NodeData<T>, T::Unprotected) {
553        // SAFETY: Since the caller asserts that we have been removed, we no longer need to be
554        // pinned.
555        let this = unsafe { &mut Pin::into_inner_unchecked(self).node };
556
557        let old_node = this.inner.take();
558        // SAFETY: In order for this type to exist, the node must be initialized.
559        let old_inner = unsafe { unwrap_unchecked(old_node) };
560        let old_shared = old_inner.shared.into_inner();
561        let data = match old_shared.protected.into_inner() {
562            NodeProtected::Linked(NodeLinked { data, .. }) => NodeData::Linked(data),
563            NodeProtected::Removed(NodeRemoved { data }) => NodeData::Removed(data),
564        };
565        (data, old_shared.unprotected)
566    }
567
568    /// Reset the node back to its initial state.
569    ///
570    /// If the node is linked, this will unlink it, and then the node will be moved to the initial
571    /// state.
572    ///
573    /// This can be thought of as a combination of [`unlink`] and [`take_removed`].
574    ///
575    /// [`unlink`]: Self::unlink
576    /// [`take_removed`]: Self::take_removed
577    ///
578    /// # Panics
579    ///
580    /// Panics if the given list is a different one than this node was registered with.
581    pub fn reset(
582        self: Pin<&'node mut Self>,
583        list: &mut PinList<T>,
584    ) -> (NodeData<T>, T::Unprotected) {
585        match self.unlink(list) {
586            Ok((protected, unprotected)) => (NodeData::Linked(protected), unprotected),
587            Err(this) => {
588                // SAFETY: `unlink` only returns `Err` if we have been removed.
589                let (removed, unprotected) = unsafe { this.take_removed_unchecked() };
590                (NodeData::Removed(removed), unprotected)
591            }
592        }
593    }
594}
595
596impl<T: ?Sized + Types> Debug for InitializedNode<'_, T>
597where
598    T::Unprotected: Debug,
599{
600    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
601        f.debug_struct("InitializedNode")
602            .field("list_id", &self.inner().list_id)
603            .field("unprotected", self.unprotected())
604            .finish()
605    }
606}
607
608/// The data stored by a node; either `Protected` or `Removed`. This type is returned by
609/// [`InitializedNode::reset`].
610pub enum NodeData<T: ?Sized + Types> {
611    /// The node was linked in a list.
612    Linked(T::Protected),
613
614    /// The node was removed from the list.
615    Removed(T::Removed),
616}
617
618impl<T: ?Sized + Types> Debug for NodeData<T>
619where
620    T::Protected: Debug,
621    T::Removed: Debug,
622{
623    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
624        match self {
625            Self::Linked(protected) => f.debug_tuple("NodeData::Linked").field(protected).finish(),
626            Self::Removed(removed) => f.debug_tuple("NodeData::Removed").field(removed).finish(),
627        }
628    }
629}