Răsfoiți Sursa

add remove function

Chen Chengjun 1 an în urmă
părinte
comite
9e59933132
5 a modificat fișierele cu 37 adăugiri și 16 ștergeri
  1. 8 2
      src/entry.rs
  2. 4 2
      src/main.rs
  3. 6 2
      src/node.rs
  4. 3 4
      src/state.rs
  5. 16 6
      src/xarray.rs

+ 8 - 2
src/entry.rs

@@ -20,7 +20,7 @@ pub trait PointerItem {
     /// 将一个裸指针转化为原指针
     ///
     /// # Safety
-    /// 裸指针必须是通过into_raw生成得到的,同时需要注意所有权的恢复。
+    /// 裸指针必须是由同类型trait里的into_raw方法生成得到的,需要注意此时所有权的恢复。
     unsafe fn from_raw(ptr: *const u8) -> Self;
 }
 
@@ -58,12 +58,14 @@ pub(crate) trait ItemEntry {
         Self: 'a;
 
     /// 由原类型生成usize,消耗原类型所有权,该usize将直接存入XArray的XEntry。
+    /// 用户需要确保生产的usize符合XArray对item entry的要求,即如果原类型是pointer的话
+    /// 后两位为00,如果原类型是usize之类的value的话末位为1.
     fn into_raw(self) -> usize;
 
     /// 由usize恢复原类型,恢复所有权
     ///
     /// # Safety
-    /// 传入的raw必须是由into_raw生成的
+    /// 传入的raw必须是由同类型trait内对应方法into_raw生成的
     unsafe fn from_raw(raw: usize) -> Self;
 
     /// 读取该类型对应的XEntry,返回用户需要的读取类型
@@ -114,6 +116,10 @@ pub(crate) struct Node {}
 
 /// XArray中有所有权的Entry,只有两种Type,Item以及Node,分别对应ItemEntry以及指向Node的Entry
 /// 指向Node的Entry目前有统一的结构类型,也就是Arc<RwLock<XNode<I>>>。
+/// OwnedEntry目前只会在三种情况下生成:
+/// - store时由传入的item生成
+/// - 创建新的Node节点时生成
+/// - replace XArray上的XEntry时,将XEntry恢复成原来的OwnedEntry (该XEntry是由OwnedEntry生成的)
 #[derive(Eq)]
 #[repr(transparent)]
 pub struct OwnedEntry<I: ItemEntry, Type> {

+ 4 - 2
src/main.rs

@@ -1,11 +1,10 @@
 #![feature(pointer_is_aligned)]
 use core::prelude::v1;
-use std::sync::Arc;
-
 use entry::*;
 use mark::*;
 use node::*;
 use state::*;
+use std::sync::Arc;
 use xarray::*;
 
 mod entry;
@@ -39,4 +38,7 @@ fn main() {
     println!("load usize: {:?}", v1);
     let v2 = xarray_usize.load(8);
     println!("load usize: {:?}", v2);
+    xarray_usize.remove(8);
+    let v2 = xarray_usize.load(8);
+    println!("load usize: {:?}", v2);
 }

+ 6 - 2
src/node.rs

@@ -61,10 +61,14 @@ impl<I: ItemEntry> XNode<I> {
     pub(crate) fn set_item_entry(
         &mut self,
         offset: u8,
-        entry: OwnedEntry<I, Item>,
+        entry: Option<OwnedEntry<I, Item>>,
     ) -> Option<OwnedEntry<I, Item>> {
         let old_entry = OwnedEntry::<I, Item>::from_raw(self.slots[offset as usize]);
-        self.slots[offset as usize] = OwnedEntry::<I, Item>::into_raw(entry);
+        let new_entry = entry
+            .map(|entry| OwnedEntry::<I, Item>::into_raw(entry))
+            .unwrap_or(XEntry::EMPTY);
+        self.slots[offset as usize] = new_entry;
+
         old_entry
     }
 

+ 3 - 4
src/state.rs

@@ -112,17 +112,16 @@ impl<I: ItemEntry, M: XMark> State<I, M> {
     pub fn store(
         &mut self,
         xa: &mut XArray<I, M>,
-        entry: OwnedEntry<I, Item>,
+        entry: Option<OwnedEntry<I, Item>>,
     ) -> Option<OwnedEntry<I, Item>> {
         let op_entry = self.create(xa);
         // TODO: Multi-index entry
-        if *op_entry == entry {
-            return Some(entry);
+        if entry.as_ref().is_some_and(|entry| *op_entry == *entry) {
+            return entry;
         }
         let node = self.node.get().unwrap();
         let mut node_write = node.write().unwrap();
         let old_entry = node_write.set_item_entry(self.offset, entry);
-        let k = node_write.entry(self.offset);
         return old_entry;
     }
 

+ 16 - 6
src/xarray.rs

@@ -11,7 +11,7 @@ pub const CHUNK_MASK: usize = CHUNK_SIZE - 1;
 /// The XArray is an abstract data type which behaves like a very large array of items.
 /// Items here must be a 8 bytes object, like pointers or `u64`.
 /// it allows you to sensibly go to the next or previous entry in a cache-efficient manner.
-/// Normal pointers may be stored in the XArray directly. They must be 4-byte aligned
+/// Normal pointers may be stored in the XArray directly. They must be 4-byte aligned.
 ///
 /// # Example
 ///
@@ -50,16 +50,21 @@ impl<I: ItemEntry, M: XMark> XArray<I, M> {
     pub fn load<'a>(&'a self, index: u64) -> Option<I::Target<'a>> {
         let mut cursor = self.cursor(index);
         let entry = cursor.current();
-        unsafe { Some(I::load_item(entry)) }
+        if entry.is_item() {
+            unsafe { Some(I::load_item(entry)) }
+        }
+        else {
+            None
+        }
     }
 
     pub fn store(&mut self, index: u64, value: I) {
         self.cursor_mut(index).store(value);
     }
 
-    // pub fn remove(&mut self, index: u64) {
-    //     self.cursor_mut(index).remove();
-    // }
+    pub fn remove(&mut self, index: u64) {
+        self.cursor_mut(index).remove();
+    }
 
     pub fn cursor<'a>(&'a self, index: u64) -> Cursor<'a, I, M> {
         Cursor {
@@ -105,7 +110,12 @@ impl<'a, I: ItemEntry, M: XMark> CursorMut<'a, I, M> {
 
     pub fn store(&mut self, item: I) {
         let Self { xa, xas } = self;
-        xas.store(xa, OwnedEntry::from_item(item));
+        xas.store(xa, Some(OwnedEntry::from_item(item)));
+    }
+
+    pub fn remove(&mut self) {
+        let Self { xa, xas } = self;
+        xas.store(xa, None);
     }
 
     pub fn key(&mut self) -> u64 {