node.rs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. use std::{marker::PhantomData, sync::Mutex};
  2. use crate::*;
  3. pub(crate) struct ReadOnly {}
  4. pub(crate) struct ReadWrite {}
  5. /// `XNode` is the intermediate node in the tree-like structure of XArray.
  6. ///
  7. /// It contains `SLOT_SIZE` number of XEntries, meaning it can accommodate up to `SLOT_SIZE` child nodes.
  8. /// The 'height' and 'offset' attributes of an XNode are determined at initialization and remain unchanged thereafter.
  9. /// XNode has a generic parameter called 'Operation', which has two possible instances: `ReadOnly` and `ReadWrite`.
  10. /// These instances indicate whether the XNode will only perform read operations or both read and write operations
  11. /// (where write operations imply potential modifications to the contents of slots).
  12. pub(crate) struct XNode<I: ItemEntry, Operation = ReadOnly> {
  13. /// The node's height from the bottom of the tree. The height of a lead node,
  14. /// which stores the user-given items, is zero.
  15. height: u8,
  16. /// This node is its parent's `offset_in_parent`-th child.
  17. /// This field is meaningless if this node is the root (will be 0).
  18. offset_in_parent: u8,
  19. inner: Mutex<XNodeInner<I>>,
  20. _marker: PhantomData<Operation>,
  21. }
  22. pub(crate) struct XNodeInner<I: ItemEntry> {
  23. slots: [XEntry<I>; SLOT_SIZE],
  24. }
  25. impl<I: ItemEntry, Operation> XNode<I, Operation> {
  26. pub(crate) fn new(height: u8, offset: u8) -> Self {
  27. Self {
  28. height,
  29. offset_in_parent: offset,
  30. inner: Mutex::new(XNodeInner::new()),
  31. _marker: PhantomData,
  32. }
  33. }
  34. /// Get the offset in the slots of the current XNode corresponding to the XEntry for the target index.
  35. pub(crate) const fn entry_offset(&self, target_index: u64) -> u8 {
  36. ((target_index >> self.height as u64) & SLOT_MASK as u64) as u8
  37. }
  38. /// Get the max index the XNode and its child nodes can store.
  39. pub(crate) fn max_index(&self) -> u64 {
  40. ((SLOT_SIZE as u64) << (self.height as u64)) - 1
  41. }
  42. pub(crate) fn height(&self) -> u8 {
  43. self.height
  44. }
  45. pub(crate) fn offset_in_parent(&self) -> u8 {
  46. self.offset_in_parent
  47. }
  48. }
  49. impl<I: ItemEntry> XNode<I, ReadOnly> {
  50. pub(crate) fn entry<'a>(&'a self, offset: u8) -> RefEntry<'a, I> {
  51. let lock = self.inner.lock().unwrap();
  52. let entry = lock.entry(offset);
  53. RefEntry::new(entry)
  54. }
  55. }
  56. impl<I: ItemEntry> XNode<I, ReadWrite> {
  57. pub(crate) fn entry<'a>(&'a self, offset: u8) -> RefEntry<'a, I> {
  58. let mut lock = self.inner.lock().unwrap();
  59. let entry = lock.entry_mut(offset);
  60. RefEntry::new(entry)
  61. }
  62. pub(crate) fn set_entry(&self, offset: u8, entry: XEntry<I>) -> XEntry<I> {
  63. self.inner.lock().unwrap().set_entry(offset, entry)
  64. }
  65. }
  66. impl<I: ItemEntry> XNodeInner<I> {
  67. pub(crate) fn new() -> Self {
  68. Self {
  69. slots: [XEntry::EMPTY; SLOT_SIZE],
  70. }
  71. }
  72. pub(crate) fn entry(&self, offset: u8) -> &XEntry<I> {
  73. &self.slots[offset as usize]
  74. }
  75. pub(crate) fn entry_mut(&mut self, offset: u8) -> &XEntry<I> {
  76. // When a modification to the target entry is needed, it first checks whether the entry is shared with other XArrays.
  77. // If it is, then it performs a copy-on-write by allocating a new entry and using it,
  78. // to prevent the modification from affecting the read or write operations on other XArrays.
  79. self.copy_on_write(
  80. unsafe { &*(&self.slots[offset as usize] as *const XEntry<I>) },
  81. offset,
  82. )
  83. }
  84. pub(crate) fn set_entry(&mut self, offset: u8, entry: XEntry<I>) -> XEntry<I> {
  85. let old_entry = core::mem::replace(&mut self.slots[offset as usize], entry);
  86. old_entry
  87. }
  88. }
  89. pub(crate) fn deep_clone_node_entry<I: ItemEntry + Clone>(entry: &XEntry<I>) -> XEntry<I> {
  90. debug_assert!(entry.is_node());
  91. let new_node = {
  92. let cloned_node: &XNode<I> = entry.as_node().unwrap();
  93. let new_node =
  94. XNode::<I, ReadWrite>::new(cloned_node.height(), cloned_node.offset_in_parent());
  95. let mut new_node_lock = new_node.inner.lock().unwrap();
  96. let cloned_node_lock = cloned_node.inner.lock().unwrap();
  97. for i in 0..SLOT_SIZE {
  98. let entry = &cloned_node_lock.slots[i];
  99. let new_entry = entry.clone();
  100. new_node_lock.slots[i as usize] = new_entry;
  101. }
  102. drop(new_node_lock);
  103. new_node
  104. };
  105. XEntry::from_node(new_node)
  106. }