xarray.rs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. use alloc::collections::VecDeque;
  2. use core::{
  3. marker::PhantomData,
  4. ops::{Deref, DerefMut},
  5. };
  6. use super::*;
  7. pub(super) const BITS_PER_LAYER: usize = 6;
  8. pub(super) const SLOT_SIZE: usize = 1 << BITS_PER_LAYER;
  9. pub(super) const SLOT_MASK: usize = SLOT_SIZE - 1;
  10. pub(super) const MAX_HEIGHT: usize = 64 / BITS_PER_LAYER + 1;
  11. /// `XArray` is an abstract data type functioning like an expansive array of items where each item must be an 8-byte object, such as `Arc<T>` or `Box<T>`.
  12. /// User-stored pointers must have a minimum alignment of 4 bytes. `XArray` facilitates efficient sequential access to adjacent entries,
  13. /// supporting multiple concurrent reads and exclusively allowing one write operation at a time.
  14. ///
  15. /// # Features
  16. /// **Copy-on-write (COW):** If items within `XArray` implement the `Clone` trait, cloning can leverage a COW mechanism.
  17. /// A clone of an `XArray` initially shares the head node with the original, avoiding immediate deep copying.
  18. /// If a mutable operation is required on either `XArray`, a deep copy of the relevant `XNode` is made first, ensuring isolated operations.
  19. ///
  20. /// **Cursors:** Interaction with `XArray` is mediated through `Cursor` and `CursorMut`.
  21. /// A `Cursor` requires an immutable reference, while `CursorMut` requires a mutable reference.
  22. /// As such, multiple `Cursor` instances can coexist, but `CursorMut` operations are singular,
  23. /// reflecting the behavior of shared (`&`) and exclusive (`&mut`) references.
  24. /// Cursors offer precise index positioning and traversal capabilities in the `XArray`.
  25. ///
  26. /// **Marking:** `XArray` enables marking of individual items or the `XArray` itself for user convenience.
  27. /// Items and the `XArray` can have up to three distinct marks by default, with each mark independently maintained.
  28. /// Marks are generally enums implementing the `ValidMark` trait. Marking is also applicable to internal nodes,
  29. /// indicating marked descendant nodes, though such marking remains transparent to users.
  30. ///
  31. /// # Example
  32. ///
  33. /// ```
  34. /// use std::sync::Arc;
  35. /// use std::sync::{Mutex, MutexGuard};
  36. /// use xarray::*;
  37. ///
  38. /// let mut xarray_arc: XArray<Arc<i32>, StdMutex> = XArray::new();
  39. /// let value = Arc::new(10);
  40. /// xarray_arc.store(333, value);
  41. /// assert!(*xarray_arc.load(333).unwrap().as_ref() == 10);
  42. ///
  43. /// let mut xarray_clone = xarray_arc.clone();
  44. /// assert!(*xarray_clone.load(333).unwrap().as_ref() == 10);
  45. /// let value = Arc::new(100);
  46. /// xarray_clone.store(333, value);
  47. ///
  48. /// assert!(*xarray_arc.load(333).unwrap().as_ref() == 10);
  49. /// assert!(*xarray_clone.load(333).unwrap().as_ref() == 100);
  50. /// ```
  51. ///
  52. /// The concepts XArray are originally introduced by Linux, which keeps the data structure of Linux's radix tree
  53. /// [Linux Radix Trees](https://lwn.net/Articles/175432/).
  54. pub struct XArray<I, L: XLock, M = NoneMark>
  55. where
  56. I: ItemEntry,
  57. M: ValidMark,
  58. {
  59. marks: [bool; 3],
  60. head: XEntry<I, L>,
  61. _marker: PhantomData<(I, M)>,
  62. }
  63. impl<I: ItemEntry, L: XLock, M: ValidMark> XArray<I, L, M> {
  64. /// Make a new, empty XArray.
  65. pub const fn new() -> Self {
  66. Self {
  67. marks: [false; 3],
  68. head: XEntry::EMPTY,
  69. _marker: PhantomData,
  70. }
  71. }
  72. /// Mark the `XArray` with the input `mark`.
  73. pub fn set_mark(&mut self, mark: M) {
  74. self.marks[mark.index()] = true;
  75. }
  76. /// Unset the input `mark` for the `XArray`.
  77. pub fn unset_mark(&mut self, mark: M) {
  78. self.marks[mark.index()] = false;
  79. }
  80. /// Judge if the `XArray` is marked with the input `mark`.
  81. pub fn is_marked(&self, mark: M) -> bool {
  82. self.marks[mark.index()]
  83. }
  84. /// Return a reference to the head entry, and later will not modify the XNode pointed to by the `head`.
  85. pub(super) fn head(&self) -> &XEntry<I, L> {
  86. &self.head
  87. }
  88. /// Return a reference to the head entry, and later may modify the XNode pointed to by the `head`.
  89. pub(super) fn head_mut(&mut self, is_exclusive: bool) -> &XEntry<I, L> {
  90. if is_exclusive {
  91. // When a modification to the head is needed, it first checks whether the head is shared with other XArrays.
  92. // If it is, then it performs COW by allocating a new head and using it,
  93. // to prevent the modification from affecting the read or write operations on other XArrays.
  94. if let Some(new_head) = self.copy_if_shared(&self.head) {
  95. self.set_head(new_head);
  96. }
  97. }
  98. &self.head
  99. }
  100. pub(super) fn max_index(&self) -> u64 {
  101. if let Some(node) = self.head.as_node() {
  102. node.height().max_index()
  103. } else {
  104. 0
  105. }
  106. }
  107. /// Set the head of the `XArray` with the new `XEntry`, and return the old `head`.
  108. pub(super) fn set_head(&mut self, head: XEntry<I, L>) -> XEntry<I, L> {
  109. let old_head = core::mem::replace(&mut self.head, head);
  110. old_head
  111. }
  112. /// Attempts to load the item at the target index within the `XArray`.
  113. /// If the target item exists, return it with `Some`, Otherwise, return `None`.
  114. pub fn load(&self, index: u64) -> Option<&I> {
  115. let mut cursor = self.cursor(index);
  116. cursor.load()
  117. }
  118. /// Stores the provided item in the `XArray` at the target index,
  119. /// and return the old item if it was previously stored in target index.
  120. pub fn store(&mut self, index: u64, item: I) -> Option<I> {
  121. let mut cursor = self.cursor_mut(index);
  122. cursor.store(item)
  123. }
  124. /// Attempts to load the item and its mark information about input `mark` at the target index within the `XArray`.
  125. /// If the target item exists, return it with `Some`, Otherwise, return `None`.
  126. pub fn load_with_mark(&self, index: u64, mark: M) -> Option<(&I, bool)> {
  127. let mut cursor = self.cursor(index);
  128. let entry = cursor.load();
  129. let mark = if entry.is_some() {
  130. cursor.is_marked(mark)
  131. } else {
  132. None
  133. };
  134. entry.map(|entry| (entry, mark.unwrap()))
  135. }
  136. /// Stores the provided item in the `XArray` at the target index and mark it with input `mark`.
  137. /// and return the old item if it was previously stored in target index.
  138. pub fn store_with_mark(&mut self, index: u64, item: I, mark: M) -> Option<I> {
  139. let mut cursor = self.cursor_mut(index);
  140. let old_item = cursor.store(item);
  141. cursor.set_mark(mark).unwrap();
  142. old_item
  143. }
  144. /// Unset the input `mark` for all of the items in the `XArray`.
  145. pub fn unset_mark_all(&mut self, mark: M) {
  146. let mut handle_list = VecDeque::new();
  147. if let Some(node) = self.head_mut(true).as_node_mut() {
  148. handle_list.push_back(node);
  149. }
  150. while !handle_list.is_empty() {
  151. let node = handle_list.pop_front().unwrap();
  152. let mut offset = 0;
  153. let node_mark = node.mark(mark.index());
  154. while (offset as usize) < SLOT_SIZE {
  155. if node_mark.is_marked(offset) {
  156. let entry = node.ref_node_entry(true, offset);
  157. if let Some(node) = entry.as_node_mut() {
  158. handle_list.push_back(node);
  159. }
  160. }
  161. offset += 1;
  162. }
  163. node.clear_mark(mark.index());
  164. }
  165. }
  166. /// Removes the `XEntry` at the target index within the `XArray`,
  167. /// and return the removed item if it was previously stored in target index.
  168. pub fn remove(&mut self, index: u64) -> Option<I> {
  169. let mut cursor = self.cursor_mut(index);
  170. cursor.remove()
  171. }
  172. /// Create an `Cursor` to perform read related operations on the `XArray`.
  173. pub fn cursor<'a>(&'a self, index: u64) -> Cursor<'a, I, L, M> {
  174. Cursor::new(self, index)
  175. }
  176. /// Create an `CursorMut` to perform read and write operations on the `XArray`.
  177. pub fn cursor_mut<'a>(&'a mut self, index: u64) -> CursorMut<'a, I, L, M> {
  178. CursorMut::new(self, index)
  179. }
  180. pub fn range<'a>(&'a self, range: core::ops::Range<u64>) -> Range<'a, I, L, M> {
  181. let cursor = Cursor::new(self, range.start);
  182. Range {
  183. cursor,
  184. end: range.end,
  185. }
  186. }
  187. }
  188. impl<I: ItemEntry + Clone, L: XLock, M: ValidMark> Clone for XArray<I, L, M> {
  189. /// Clone with cow mechanism.
  190. fn clone(&self) -> Self {
  191. let cloned_head = self.head.clone();
  192. Self {
  193. marks: self.marks,
  194. head: cloned_head,
  195. _marker: PhantomData,
  196. }
  197. }
  198. }
  199. pub trait ValidLock<T>: Sized {
  200. type Target<'a>: Deref<Target = T> + DerefMut<Target = T>
  201. where
  202. Self: 'a;
  203. fn new(inner: T) -> Self;
  204. fn lock(&self) -> Self::Target<'_>;
  205. }
  206. pub trait XLock {
  207. type Lock<T>: ValidLock<T>;
  208. fn new<T>(inner: T) -> Self::Lock<T> {
  209. Self::Lock::<T>::new(inner)
  210. }
  211. }
  212. #[macro_export]
  213. macro_rules! abstract_lock_to {
  214. ($lock_type:ident, $name:ident) => {
  215. pub struct $name;
  216. impl XLock for $name {
  217. type Lock<T> = $lock_type<T>;
  218. }
  219. };
  220. }
  221. pub struct Range<'a, I, L, M>
  222. where
  223. I: ItemEntry,
  224. L: XLock,
  225. M: ValidMark,
  226. {
  227. cursor: Cursor<'a, I, L, M>,
  228. end: u64,
  229. }
  230. impl<'a, I: ItemEntry, L: XLock, M: ValidMark> core::iter::Iterator for Range<'a, I, L, M> {
  231. type Item = (u64, &'a I);
  232. fn next(&mut self) -> Option<Self::Item> {
  233. loop {
  234. if self.cursor.index() >= self.end {
  235. return None;
  236. }
  237. let item = self.cursor.load();
  238. if item.is_none() {
  239. self.cursor.next();
  240. continue;
  241. }
  242. let res = item.map(|item| (self.cursor.index(), item));
  243. self.cursor.next();
  244. return res;
  245. }
  246. }
  247. }