pin_list/
lib.rs

1//! This crate provides `PinList`, a safe `Pin`-based intrusive doubly linked list.
2//!
3//! # Example
4//!
5//! A thread-safe unfair async mutex.
6//!
7//! ```
8//! use pin_project_lite::pin_project;
9//! use std::cell::UnsafeCell;
10//! use std::future::Future;
11//! use std::ops::Deref;
12//! use std::ops::DerefMut;
13//! use std::pin::Pin;
14//! use std::task;
15//! use std::task::Poll;
16//! use pin_list::PinList;
17//!
18//! type PinListTypes = dyn pin_list::Types<
19//!     Id = pin_list::id::Checked,
20//!     Protected = task::Waker,
21//!     Removed = (),
22//!     Unprotected = (),
23//! >;
24//!
25//! pub struct Mutex<T> {
26//!     data: UnsafeCell<T>,
27//!     inner: std::sync::Mutex<Inner>,
28//! }
29//!
30//! struct Inner {
31//!     locked: bool,
32//!     waiters: PinList<PinListTypes>,
33//! }
34//!
35//! unsafe impl<T> Sync for Mutex<T> {}
36//!
37//! impl<T> Mutex<T> {
38//!     pub fn new(data: T) -> Self {
39//!         Self {
40//!             data: UnsafeCell::new(data),
41//!             inner: std::sync::Mutex::new(Inner {
42//!                 locked: false,
43//!                 waiters: PinList::new(pin_list::id::Checked::new()),
44//!             }),
45//!         }
46//!     }
47//!     pub fn lock(&self) -> Lock<'_, T> {
48//!         Lock {
49//!             mutex: self,
50//!             node: pin_list::Node::new(),
51//!         }
52//!     }
53//! }
54//!
55//! pin_project! {
56//!     pub struct Lock<'mutex, T> {
57//!         mutex: &'mutex Mutex<T>,
58//!         #[pin]
59//!         node: pin_list::Node<PinListTypes>,
60//!     }
61//!
62//!     impl<T> PinnedDrop for Lock<'_, T> {
63//!         fn drop(this: Pin<&mut Self>) {
64//!             let this = this.project();
65//!             let node = match this.node.initialized_mut() {
66//!                 // The future was cancelled before it could complete.
67//!                 Some(initialized) => initialized,
68//!                 // The future has completed already (or hasn't started); we don't have to do
69//!                 // anything.
70//!                 None => return,
71//!             };
72//!
73//!             let mut inner = this.mutex.inner.lock().unwrap();
74//!
75//!             match node.reset(&mut inner.waiters) {
76//!                 // If we've cancelled the future like usual, just do that.
77//!                 (pin_list::NodeData::Linked(_waker), ()) => {}
78//!
79//!                 // Otherwise, we have been woken but aren't around to take the lock. To
80//!                 // prevent deadlocks, pass the notification on to someone else.
81//!                 (pin_list::NodeData::Removed(()), ()) => {
82//!                     if let Ok(waker) = inner.waiters.cursor_front_mut().remove_current(()) {
83//!                         drop(inner);
84//!                         waker.wake();
85//!                     }
86//!                 }
87//!             }
88//!         }
89//!     }
90//! }
91//!
92//! impl<'mutex, T> Future for Lock<'mutex, T> {
93//!     type Output = Guard<'mutex, T>;
94//!     fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
95//!         let mut this = self.project();
96//!
97//!         let mut inner = this.mutex.inner.lock().unwrap();
98//!
99//!         if let Some(mut node) = this.node.as_mut().initialized_mut() {
100//!             // Check whether we've been woken up, only continuing if so.
101//!             if let Err(node) = node.take_removed(&inner.waiters) {
102//!                 // If we haven't been woken, re-register our waker and pend.
103//!                 *node.protected_mut(&mut inner.waiters).unwrap() = cx.waker().clone();
104//!                 return Poll::Pending;
105//!             }
106//!         }
107//!
108//!         // If the mutex is unlocked, mark it as locked and return the guard
109//!         if !inner.locked {
110//!             inner.locked = true;
111//!             return Poll::Ready(Guard { mutex: this.mutex });
112//!         }
113//!
114//!         // Otherwise, re-register ourselves to be woken when the mutex is unlocked again
115//!         inner.waiters.push_back(this.node, cx.waker().clone(), ());
116//!
117//!         Poll::Pending
118//!     }
119//! }
120//!
121//! pub struct Guard<'mutex, T> {
122//!     mutex: &'mutex Mutex<T>,
123//! }
124//!
125//! impl<T> Deref for Guard<'_, T> {
126//!     type Target = T;
127//!     fn deref(&self) -> &Self::Target {
128//!         unsafe { &*self.mutex.data.get() }
129//!     }
130//! }
131//! impl<T> DerefMut for Guard<'_, T> {
132//!     fn deref_mut(&mut self) -> &mut Self::Target {
133//!         unsafe { &mut *self.mutex.data.get() }
134//!     }
135//! }
136//!
137//! impl<T> Drop for Guard<'_, T> {
138//!     fn drop(&mut self) {
139//!         let mut inner = self.mutex.inner.lock().unwrap();
140//!         inner.locked = false;
141//!
142//!         if let Ok(waker) = inner.waiters.cursor_front_mut().remove_current(()) {
143//!             drop(inner);
144//!             waker.wake();
145//!         }
146//!     }
147//! }
148//! #
149//! # fn assert_send<T: Send>(_: T) {}
150//! # let mutex = Mutex::new(());
151//! # assert_send(mutex.lock());
152//! ```
153#![warn(
154    clippy::pedantic,
155    missing_debug_implementations,
156    missing_docs,
157    noop_method_call,
158    trivial_casts,
159    trivial_numeric_casts,
160    unsafe_op_in_unsafe_fn,
161    unused_lifetimes,
162    unused_qualifications
163)]
164#![allow(
165    clippy::items_after_statements,
166
167    // Repetition is used in `Send`+`Sync` bounds so each one can be individually commented.
168    clippy::type_repetition_in_bounds,
169
170    // This is a silly lint; I always turbofish the transmute so it's fine
171    clippy::transmute_ptr_to_ptr,
172
173    // Has false positives: https://github.com/rust-lang/rust-clippy/issues/7812
174    clippy::redundant_closure,
175
176    // I export all the types at the crate root, so this lint is pointless.
177    clippy::module_name_repetitions,
178)]
179#![no_std]
180
181#[cfg(feature = "alloc")]
182extern crate alloc;
183
184#[cfg(feature = "std")]
185extern crate std;
186
187pub mod id;
188pub use id::Id;
189
190mod list;
191pub use list::{Cursor, CursorMut, PinList, Types};
192
193mod node;
194pub use node::{InitializedNode, Node, NodeData};
195
196mod util;
197
198#[cfg(all(test, feature = "std"))]
199mod tests {
200    use crate::id;
201    use core::pin::Pin;
202    use pin_utils::pin_mut as pin;
203    use std::boxed::Box;
204    use std::panic;
205    use std::process::abort;
206    use std::ptr;
207
208    type PinListTypes = dyn crate::Types<
209        Id = id::Checked,
210        // Use boxes because they better detect double-frees, type mismatches and other errors.
211        Protected = Box<u8>,
212        Removed = Box<u16>,
213        Unprotected = Box<u32>,
214    >;
215    type PinList = crate::PinList<PinListTypes>;
216
217    #[test]
218    fn empty_lists() {
219        let mut list = PinList::new(id::Checked::new());
220        let list_ptr: *const _ = &list;
221
222        let assert_ghost_cursor = |cursor: crate::Cursor<'_, _>| {
223            assert!(ptr::eq(cursor.list(), list_ptr));
224            assert_eq!(cursor.protected(), None);
225            assert_eq!(cursor.unprotected(), None);
226        };
227        let assert_ghost_cursor_mut = |mut cursor: crate::CursorMut<'_, _>| {
228            assert!(ptr::eq(cursor.list(), list_ptr));
229            assert_eq!(cursor.protected(), None);
230            assert_eq!(cursor.protected_mut(), None);
231            assert_eq!(cursor.unprotected(), None);
232            assert_eq!(cursor.remove_current(Box::new(5)), Err(Box::new(5)));
233            assert!(!cursor.remove_current_with(|_| abort()));
234            assert!(!cursor.remove_current_with_or(|_| abort(), || abort()));
235            assert_ghost_cursor(cursor.as_shared());
236        };
237
238        assert!(list.is_empty());
239
240        assert_ghost_cursor(list.cursor_ghost());
241        assert_ghost_cursor(list.cursor_front());
242        assert_ghost_cursor(list.cursor_back());
243        assert_ghost_cursor_mut(list.cursor_ghost_mut());
244        assert_ghost_cursor_mut(list.cursor_front_mut());
245        assert_ghost_cursor_mut(list.cursor_back_mut());
246    }
247
248    #[test]
249    fn single_node_with_unlink() {
250        let mut list = PinList::new(id::Checked::new());
251
252        let node = crate::Node::new();
253        pin!(node);
254        assert!(node.is_initial());
255        assert!(node.initialized().is_none());
256        assert!(node.as_mut().initialized_mut().is_none());
257
258        let mut protected = Box::new(0);
259        let unprotected = Box::new(1);
260        list.push_front(node.as_mut(), protected.clone(), unprotected.clone());
261
262        assert!(!node.is_initial());
263
264        let initialized = node.initialized().unwrap();
265        assert_eq!(initialized.unprotected(), &unprotected);
266        assert_eq!(initialized.protected(&list), Some(&protected));
267        assert_eq!(initialized.protected_mut(&mut list), Some(&mut protected));
268
269        let initialized = node.as_mut().initialized_mut().unwrap();
270        assert_eq!(initialized.unprotected(), &unprotected);
271        assert_eq!(initialized.protected(&list), Some(&protected));
272        assert_eq!(initialized.protected_mut(&mut list), Some(&mut protected));
273
274        assert!(!list.is_empty());
275
276        let check_cursor = |mut cursor: crate::Cursor<'_, _>| {
277            assert_eq!(cursor.protected().unwrap(), &protected);
278            assert_eq!(cursor.unprotected().unwrap(), &unprotected);
279            cursor.move_next();
280            assert_eq!(cursor.protected(), None);
281            for _ in 0..10 {
282                cursor.move_previous();
283                assert_eq!(cursor.protected().unwrap(), &protected);
284                cursor.move_previous();
285                assert_eq!(cursor.protected(), None);
286            }
287        };
288        let check_cursor_mut = |mut cursor: crate::CursorMut<'_, _>| {
289            assert_eq!(cursor.protected().unwrap(), &protected);
290            assert_eq!(cursor.protected_mut().unwrap(), &protected);
291            assert_eq!(cursor.unprotected().unwrap(), &unprotected);
292            for _ in 0..7 {
293                cursor.move_next();
294                assert_eq!(cursor.protected(), None);
295                cursor.move_next();
296                assert_eq!(cursor.protected().unwrap(), &protected);
297            }
298            for _ in 0..10 {
299                cursor.move_previous();
300                assert_eq!(cursor.protected(), None);
301                cursor.move_previous();
302                assert_eq!(cursor.protected().unwrap(), &protected);
303            }
304            check_cursor(cursor.as_shared());
305            check_cursor(cursor.into_shared());
306        };
307
308        check_cursor(list.cursor_front());
309        check_cursor(list.cursor_back());
310        check_cursor_mut(list.cursor_front_mut());
311        check_cursor_mut(list.cursor_back_mut());
312
313        assert_eq!(
314            initialized.unlink(&mut list).unwrap(),
315            (protected, unprotected)
316        );
317
318        assert!(node.is_initial());
319        assert!(node.initialized().is_none());
320        assert!(node.as_mut().initialized_mut().is_none());
321
322        assert!(list.is_empty());
323    }
324
325    #[test]
326    fn removal() {
327        let mut list = PinList::new(id::Checked::new());
328
329        let node = crate::Node::new();
330        pin!(node);
331
332        let protected = Box::new(0);
333        let removed = Box::new(1);
334        let unprotected = Box::new(2);
335
336        let initialized_node =
337            list.push_back(node.as_mut(), protected.clone(), unprotected.clone());
338
339        assert_eq!(
340            list.cursor_front_mut()
341                .remove_current(removed.clone())
342                .unwrap(),
343            protected
344        );
345
346        assert_eq!(
347            initialized_node.take_removed(&list).unwrap(),
348            (removed, unprotected)
349        );
350        assert!(node.is_initial());
351        assert!(list.is_empty());
352    }
353
354    #[test]
355    fn removal_fallback() {
356        let mut list = PinList::new(id::Checked::new());
357
358        let node = crate::Node::new();
359        pin!(node);
360
361        let protected = Box::new(0);
362        let removed = Box::new(1);
363        let unprotected = Box::new(2);
364
365        let initialized_node =
366            list.push_front(node.as_mut(), protected.clone(), unprotected.clone());
367
368        let mut cursor = list.cursor_front_mut();
369        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
370            cursor.remove_current_with_or(
371                |p| {
372                    assert_eq!(p, protected);
373                    panic::panic_any(491_u32)
374                },
375                || removed.clone(),
376            )
377        }));
378        assert_eq!(cursor.protected(), None);
379        assert_eq!(res.unwrap_err().downcast::<u32>().unwrap(), Box::new(491));
380
381        assert_eq!(
382            initialized_node.take_removed(&list).unwrap(),
383            (removed, unprotected),
384        );
385        assert!(node.is_initial());
386        assert!(list.is_empty());
387    }
388
389    #[test]
390    fn multinode() {
391        let mut list = PinList::new(id::Checked::new());
392
393        let mut nodes = (0..7)
394            .map(|_| Box::pin(crate::Node::new()))
395            .collect::<Box<[_]>>();
396
397        fn assert_order<const N: usize>(list: &mut PinList, order: [u8; N]) {
398            // Forwards iteration
399            let mut cursor = list.cursor_ghost_mut();
400            for number in order {
401                cursor.move_next();
402                assert_eq!(**cursor.protected().unwrap(), number);
403                assert_eq!(**cursor.protected_mut().unwrap(), number);
404                assert_eq!(**cursor.unprotected().unwrap(), u32::from(number));
405            }
406            cursor.move_next();
407            assert_eq!(cursor.protected(), None);
408            assert_eq!(cursor.protected_mut(), None);
409            assert_eq!(cursor.unprotected(), None);
410
411            // Reverse iteration
412            for number in order.into_iter().rev() {
413                cursor.move_previous();
414                assert_eq!(**cursor.protected().unwrap(), number);
415                assert_eq!(**cursor.protected_mut().unwrap(), number);
416                assert_eq!(**cursor.unprotected().unwrap(), u32::from(number));
417            }
418            cursor.move_previous();
419            assert_eq!(cursor.protected(), None);
420            assert_eq!(cursor.protected_mut(), None);
421            assert_eq!(cursor.unprotected(), None);
422        }
423
424        fn cursor(list: &mut PinList, index: usize) -> crate::CursorMut<'_, PinListTypes> {
425            let mut cursor = list.cursor_front_mut();
426            for _ in 0..index {
427                cursor.move_next();
428                cursor.protected().unwrap();
429            }
430            cursor
431        }
432
433        // ghost before; ghost after
434        list.cursor_ghost_mut()
435            .insert_before(nodes[0].as_mut(), Box::new(0), Box::new(0));
436        assert_order(&mut list, [0]);
437
438        // ghost before; node after; insert_after
439        list.cursor_ghost_mut()
440            .insert_after(nodes[1].as_mut(), Box::new(1), Box::new(1));
441        assert_order(&mut list, [1, 0]);
442
443        // ghost before; node after; insert_before
444        cursor(&mut list, 0).insert_before(nodes[2].as_mut(), Box::new(2), Box::new(2));
445        assert_order(&mut list, [2, 1, 0]);
446
447        // node before; ghost after; insert_after
448        cursor(&mut list, 2).insert_after(nodes[3].as_mut(), Box::new(3), Box::new(3));
449        assert_order(&mut list, [2, 1, 0, 3]);
450
451        // node before; ghost after; insert_before
452        list.cursor_ghost_mut()
453            .insert_before(nodes[4].as_mut(), Box::new(4), Box::new(4));
454        assert_order(&mut list, [2, 1, 0, 3, 4]);
455
456        // node before; node after; insert_after
457        cursor(&mut list, 0).insert_after(nodes[5].as_mut(), Box::new(5), Box::new(5));
458        assert_order(&mut list, [2, 5, 1, 0, 3, 4]);
459
460        // node before; node after; insert_before
461        cursor(&mut list, 1).insert_before(nodes[6].as_mut(), Box::new(6), Box::new(6));
462        assert_order(&mut list, [2, 6, 5, 1, 0, 3, 4]);
463
464        fn unlink(
465            list: &mut PinList,
466            nodes: &mut [Pin<Box<crate::Node<PinListTypes>>>],
467            index: u8,
468        ) {
469            let node = nodes[usize::from(index)].as_mut();
470            let node = node.initialized_mut().expect("already unlinked");
471            let (protected, unprotected) = node.unlink(list).unwrap();
472            assert_eq!(*protected, index);
473            assert_eq!(*unprotected, u32::from(index));
474        }
475
476        fn remove(
477            list: &mut PinList,
478            nodes: &mut [Pin<Box<crate::Node<PinListTypes>>>],
479            index: u8,
480        ) {
481            let node = nodes[usize::from(index)].as_mut();
482            let node = node.initialized_mut().expect("already unlinked");
483            let mut cursor = node.cursor_mut(&mut *list).unwrap();
484            let removed = Box::new(u16::from(index));
485            assert_eq!(*cursor.remove_current(removed).unwrap(), index);
486            let (removed, unprotected) = node.take_removed(&*list).unwrap();
487            assert_eq!(*removed, u16::from(index));
488            assert_eq!(*unprotected, u32::from(index));
489        }
490
491        // node before; node after; unlink
492        unlink(&mut list, &mut nodes, 6);
493        assert_order(&mut list, [2, 5, 1, 0, 3, 4]);
494
495        // node before; node after; remove
496        remove(&mut list, &mut nodes, 5);
497        assert_order(&mut list, [2, 1, 0, 3, 4]);
498
499        // node before; ghost after; unlink
500        unlink(&mut list, &mut nodes, 4);
501        assert_order(&mut list, [2, 1, 0, 3]);
502
503        // node before; ghost after; remove
504        remove(&mut list, &mut nodes, 3);
505        assert_order(&mut list, [2, 1, 0]);
506
507        // ghost before; node after; unlink
508        unlink(&mut list, &mut nodes, 2);
509        assert_order(&mut list, [1, 0]);
510
511        // ghost before; node after; remove
512        remove(&mut list, &mut nodes, 1);
513        assert_order(&mut list, [0]);
514
515        // ghost before; ghost after; unlink
516        unlink(&mut list, &mut nodes, 0);
517        assert_order(&mut list, []);
518    }
519}