entry.rs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. use alloc::boxed::Box;
  2. use alloc::sync::Arc;
  3. use core::marker::PhantomData;
  4. use core::mem::ManuallyDrop;
  5. use core::ops::{Deref, Not};
  6. use crate::node::{TryClone, XNode};
  7. /// A trait that should be implemented for the types users wish to store in an `XArray`.
  8. /// Items stored in an XArray are required to be 8 bytes in size, Currently it can be various pointer types.
  9. ///
  10. /// # Safety
  11. /// Users must ensure that the produced `usize` of `into_raw()` meets the requirements for an item entry
  12. /// in the XArray. Specifically, if the original type is a pointer, the last two bits should be 00;
  13. /// if the original type is a value like usize, the last bit should be 1 (TODO).
  14. pub unsafe trait ItemEntry {
  15. /// Converts the original type into a `usize`, consuming the ownership of the original type.
  16. ///
  17. /// This `usize` should be directly stored in an XArray's XEntry.
  18. fn into_raw(self) -> usize;
  19. /// Recovers the original type from a usize, reclaiming ownership.
  20. ///
  21. /// # Safety
  22. /// The raw value passed must have been produced by the corresponding `into_raw` method in this trait
  23. /// from the same type.
  24. unsafe fn from_raw(raw: usize) -> Self;
  25. }
  26. unsafe impl<T> ItemEntry for Arc<T> {
  27. fn into_raw(self) -> usize {
  28. let raw_ptr = Arc::into_raw(self);
  29. debug_assert!(raw_ptr.is_aligned_to(4));
  30. raw_ptr as usize
  31. }
  32. unsafe fn from_raw(raw: usize) -> Self {
  33. unsafe { Arc::from_raw(raw as *mut T) }
  34. }
  35. }
  36. unsafe impl<T> ItemEntry for Box<T> {
  37. fn into_raw(self) -> usize {
  38. let raw_ptr = Box::into_raw(self) as *const u8;
  39. debug_assert!(raw_ptr.is_aligned_to(4));
  40. raw_ptr as usize
  41. }
  42. unsafe fn from_raw(raw: usize) -> Self {
  43. Box::from_raw(raw as *mut _)
  44. }
  45. }
  46. #[derive(PartialEq, Debug)]
  47. pub struct ItemRef<'a, I>
  48. where
  49. I: ItemEntry,
  50. {
  51. item: ManuallyDrop<I>,
  52. _marker: PhantomData<&'a I>,
  53. }
  54. impl<'a, I: ItemEntry> Deref for ItemRef<'a, I> {
  55. type Target = I;
  56. fn deref(&self) -> &I {
  57. &*self.item
  58. }
  59. }
  60. /// The type stored in the head of `XArray` and the slots of `XNode`s, which is the basic unit of storage
  61. /// within an XArray.
  62. ///
  63. /// There are the following types of `XEntry`:
  64. /// - Internal entries: These are invisible to users and have the last two bits set to 10. Currently `XArray`
  65. /// only have node entries as internal entries, which are entries that point to XNodes.
  66. /// - Item entries: Items stored by the user. Currently stored items can only be pointers and the last two bits
  67. /// of these item entries are 00.
  68. ///
  69. /// `XEntry` have the ownership. Once it generated from an item or a XNode, the ownership of the item or the XNode
  70. /// will be transferred to the `XEntry`. If the stored item in the XArray implemented Clone trait, then the XEntry
  71. /// in the XArray can also implement Clone trait.
  72. #[derive(PartialEq, Eq, Debug)]
  73. #[repr(transparent)]
  74. pub(super) struct XEntry<I>
  75. where
  76. I: ItemEntry,
  77. {
  78. raw: usize,
  79. _marker: core::marker::PhantomData<(Arc<XNode<I>>, I)>,
  80. }
  81. #[derive(PartialEq, Eq, Debug)]
  82. #[repr(usize)]
  83. enum EntryType {
  84. Node = 0,
  85. Item = 2,
  86. }
  87. impl TryFrom<usize> for EntryType {
  88. type Error = ();
  89. fn try_from(val: usize) -> Result<Self, Self::Error> {
  90. match val {
  91. x if x == EntryType::Node as usize => Ok(EntryType::Node),
  92. x if x == EntryType::Item as usize => Ok(EntryType::Item),
  93. _ => Err(()),
  94. }
  95. }
  96. }
  97. impl<I: ItemEntry> XEntry<I> {
  98. const TYPE_MASK: usize = 3;
  99. pub const EMPTY: Self = Self {
  100. raw: 0,
  101. _marker: PhantomData,
  102. };
  103. unsafe fn new(ptr: usize, ty: EntryType) -> Self {
  104. debug_assert!(ptr & Self::TYPE_MASK == 0);
  105. Self {
  106. raw: ptr | (ty as usize),
  107. _marker: PhantomData,
  108. }
  109. }
  110. fn ptr(&self) -> usize {
  111. self.raw & !Self::TYPE_MASK
  112. }
  113. fn ty(&self) -> Option<EntryType> {
  114. self.is_null()
  115. .not()
  116. .then(|| (self.raw & Self::TYPE_MASK).try_into().unwrap())
  117. }
  118. pub fn is_null(&self) -> bool {
  119. self.raw == 0
  120. }
  121. }
  122. pub(super) enum NodeMaybeMut<'a, I>
  123. where
  124. I: ItemEntry,
  125. {
  126. Shared(&'a XNode<I>),
  127. Exclusive(&'a mut XNode<I>),
  128. }
  129. impl<'a, I: ItemEntry> Deref for NodeMaybeMut<'a, I> {
  130. type Target = XNode<I>;
  131. fn deref(&self) -> &XNode<I> {
  132. match &self {
  133. Self::Shared(ref node) => node,
  134. Self::Exclusive(ref node) => node,
  135. }
  136. }
  137. }
  138. impl<I: ItemEntry> XEntry<I> {
  139. pub fn from_node(node: XNode<I>) -> Self {
  140. let node_ptr = {
  141. let arc_node = Arc::new(node);
  142. Arc::into_raw(arc_node) as usize
  143. };
  144. unsafe { Self::new(node_ptr, EntryType::Node) }
  145. }
  146. pub fn is_node(&self) -> bool {
  147. self.ty() == Some(EntryType::Node)
  148. }
  149. pub fn as_node_ref(&self) -> Option<&XNode<I>> {
  150. if !self.is_node() {
  151. return None;
  152. }
  153. Some(unsafe { &*(self.ptr() as *const XNode<I>) })
  154. }
  155. pub fn as_node_maybe_mut(&mut self) -> Option<NodeMaybeMut<'_, I>> {
  156. match self.node_strong_count() {
  157. 0 => None,
  158. 1 => Some(NodeMaybeMut::Exclusive(unsafe {
  159. &mut *(self.ptr() as *mut _)
  160. })),
  161. _ => Some(NodeMaybeMut::Shared(unsafe { &*(self.ptr() as *const _) })),
  162. }
  163. }
  164. pub fn as_node_mut_or_cow(&mut self) -> Option<&mut XNode<I>> {
  165. match self.node_strong_count() {
  166. 0 => return None,
  167. 1 => return Some(unsafe { &mut *(self.ptr() as *mut _) }),
  168. _ => (),
  169. }
  170. let node = unsafe { &*(self.ptr() as *const XNode<I>) };
  171. let new_node = node.try_clone().unwrap();
  172. *self = Self::from_node(new_node);
  173. Some(unsafe { &mut *(self.ptr() as *mut XNode<I>) })
  174. }
  175. fn node_strong_count(&self) -> usize {
  176. if !self.is_node() {
  177. return 0;
  178. }
  179. let node = unsafe { ManuallyDrop::new(Arc::from_raw(self.ptr() as *const XNode<I>)) };
  180. Arc::strong_count(&*node)
  181. }
  182. }
  183. impl<I: ItemEntry> XEntry<I> {
  184. pub fn from_item(item: I) -> Self {
  185. let item_ptr = I::into_raw(item) as usize;
  186. unsafe { Self::new(item_ptr, EntryType::Item) }
  187. }
  188. pub fn is_item(&self) -> bool {
  189. self.ty() == Some(EntryType::Item)
  190. }
  191. pub fn into_item(self) -> Option<I> {
  192. if !self.is_item() {
  193. return None;
  194. }
  195. let ptr = self.ptr();
  196. core::mem::forget(self);
  197. Some(unsafe { I::from_raw(ptr) })
  198. }
  199. pub fn as_item_ref(&self) -> Option<ItemRef<'_, I>> {
  200. if !self.is_item() {
  201. return None;
  202. }
  203. let ptr = self.ptr();
  204. Some(ItemRef {
  205. item: unsafe { ManuallyDrop::new(I::from_raw(ptr)) },
  206. _marker: PhantomData,
  207. })
  208. }
  209. }
  210. impl<I: ItemEntry> Drop for XEntry<I> {
  211. fn drop(&mut self) {
  212. match self.ty() {
  213. None => (),
  214. Some(EntryType::Item) => unsafe {
  215. I::from_raw(self.ptr());
  216. },
  217. Some(EntryType::Node) => unsafe {
  218. Arc::from_raw(self.ptr() as *const XNode<I>);
  219. },
  220. }
  221. }
  222. }
  223. impl<I: ItemEntry + Clone> Clone for XEntry<I> {
  224. fn clone(&self) -> Self {
  225. match self.ty() {
  226. None => Self::EMPTY,
  227. Some(EntryType::Item) => unsafe {
  228. let item_entry = ManuallyDrop::new(I::from_raw(self.ptr()));
  229. Self::from_item((*item_entry).clone())
  230. },
  231. Some(EntryType::Node) => unsafe {
  232. Arc::increment_strong_count(self.ptr() as *const XNode<I>);
  233. Self {
  234. raw: self.raw,
  235. _marker: PhantomData,
  236. }
  237. },
  238. }
  239. }
  240. }