linked_list.rs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // SPDX-License-Identifier: Apache-2.0 OR MIT
  2. #![allow(clippy::undocumented_unsafe_blocks)]
  3. #![cfg_attr(feature = "alloc", feature(allocator_api))]
  4. #![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]
  5. use core::{
  6. cell::Cell,
  7. marker::PhantomPinned,
  8. pin::Pin,
  9. ptr::{self, NonNull},
  10. };
  11. use pin_init::*;
  12. #[allow(unused_attributes)]
  13. mod error;
  14. #[allow(unused_imports)]
  15. use error::Error;
  16. #[pin_data(PinnedDrop)]
  17. #[repr(C)]
  18. #[derive(Debug)]
  19. pub struct ListHead {
  20. next: Link,
  21. prev: Link,
  22. #[pin]
  23. pin: PhantomPinned,
  24. }
  25. impl ListHead {
  26. #[inline]
  27. pub fn new() -> impl PinInit<Self> {
  28. pin_init!(&this in Self {
  29. next: unsafe { Link::new_unchecked(this) },
  30. prev: unsafe { Link::new_unchecked(this) },
  31. pin: PhantomPinned,
  32. })
  33. }
  34. #[inline]
  35. #[allow(dead_code)]
  36. pub fn insert_next(list: &ListHead) -> impl PinInit<Self> + '_ {
  37. pin_init!(&this in Self {
  38. prev: list.next.prev().replace(unsafe { Link::new_unchecked(this)}),
  39. next: list.next.replace(unsafe { Link::new_unchecked(this)}),
  40. pin: PhantomPinned,
  41. })
  42. }
  43. #[inline]
  44. pub fn insert_prev(list: &ListHead) -> impl PinInit<Self> + '_ {
  45. pin_init!(&this in Self {
  46. next: list.prev.next().replace(unsafe { Link::new_unchecked(this)}),
  47. prev: list.prev.replace(unsafe { Link::new_unchecked(this)}),
  48. pin: PhantomPinned,
  49. })
  50. }
  51. #[inline]
  52. pub fn next(&self) -> Option<NonNull<Self>> {
  53. if ptr::eq(self.next.as_ptr(), self) {
  54. None
  55. } else {
  56. Some(unsafe { NonNull::new_unchecked(self.next.as_ptr() as *mut Self) })
  57. }
  58. }
  59. #[allow(dead_code)]
  60. pub fn size(&self) -> usize {
  61. let mut size = 1;
  62. let mut cur = self.next.clone();
  63. while !ptr::eq(self, cur.cur()) {
  64. cur = cur.next().clone();
  65. size += 1;
  66. }
  67. size
  68. }
  69. }
  70. #[pinned_drop]
  71. impl PinnedDrop for ListHead {
  72. //#[inline]
  73. fn drop(self: Pin<&mut Self>) {
  74. if !ptr::eq(self.next.as_ptr(), &*self) {
  75. let next = unsafe { &*self.next.as_ptr() };
  76. let prev = unsafe { &*self.prev.as_ptr() };
  77. next.prev.set(&self.prev);
  78. prev.next.set(&self.next);
  79. }
  80. }
  81. }
  82. #[repr(transparent)]
  83. #[derive(Clone, Debug)]
  84. struct Link(Cell<NonNull<ListHead>>);
  85. impl Link {
  86. /// # Safety
  87. ///
  88. /// The contents of the pointer should form a consistent circular
  89. /// linked list; for example, a "next" link should be pointed back
  90. /// by the target `ListHead`'s "prev" link and a "prev" link should be
  91. /// pointed back by the target `ListHead`'s "next" link.
  92. #[inline]
  93. unsafe fn new_unchecked(ptr: NonNull<ListHead>) -> Self {
  94. Self(Cell::new(ptr))
  95. }
  96. #[inline]
  97. fn next(&self) -> &Link {
  98. unsafe { &(*self.0.get().as_ptr()).next }
  99. }
  100. #[inline]
  101. #[allow(dead_code)]
  102. fn prev(&self) -> &Link {
  103. unsafe { &(*self.0.get().as_ptr()).prev }
  104. }
  105. #[allow(dead_code)]
  106. fn cur(&self) -> &ListHead {
  107. unsafe { &*self.0.get().as_ptr() }
  108. }
  109. #[inline]
  110. fn replace(&self, other: Link) -> Link {
  111. unsafe { Link::new_unchecked(self.0.replace(other.0.get())) }
  112. }
  113. #[inline]
  114. fn as_ptr(&self) -> *const ListHead {
  115. self.0.get().as_ptr()
  116. }
  117. #[inline]
  118. fn set(&self, val: &Link) {
  119. self.0.set(val.0.get());
  120. }
  121. }
  122. #[allow(dead_code)]
  123. #[cfg(not(any(feature = "std", feature = "alloc")))]
  124. fn main() {}
  125. #[allow(dead_code)]
  126. #[cfg_attr(test, test)]
  127. #[cfg(any(feature = "std", feature = "alloc"))]
  128. fn main() -> Result<(), Error> {
  129. let a = Box::pin_init(ListHead::new())?;
  130. stack_pin_init!(let b = ListHead::insert_next(&a));
  131. stack_pin_init!(let c = ListHead::insert_next(&a));
  132. stack_pin_init!(let d = ListHead::insert_next(&b));
  133. let e = Box::pin_init(ListHead::insert_next(&b))?;
  134. println!("a ({a:p}): {a:?}");
  135. println!("b ({b:p}): {b:?}");
  136. println!("c ({c:p}): {c:?}");
  137. println!("d ({d:p}): {d:?}");
  138. println!("e ({e:p}): {e:?}");
  139. let mut inspect = &*a;
  140. while let Some(next) = inspect.next() {
  141. println!("({inspect:p}): {inspect:?}");
  142. inspect = unsafe { &*next.as_ptr() };
  143. if core::ptr::eq(inspect, &*a) {
  144. break;
  145. }
  146. }
  147. Ok(())
  148. }