#cursor #data-structures #array #write #entries #object

nightly no-std xarray

A Rust 版本的 XArray,具有写时复制的能力

2 个版本

0.1.1 2024年7月8日
0.1.0 2024年6月3日

198并发

Download history 126/week @ 2024-05-31 22/week @ 2024-06-07 2/week @ 2024-06-14 7/week @ 2024-06-28 140/week @ 2024-07-05 39/week @ 2024-07-12 50/week @ 2024-07-19 69/week @ 2024-07-26 51/week @ 2024-08-02 57/week @ 2024-08-09

每月下载量 234
用于 ostd

MPL-2.0 许可证

87KB
1.5K SLoC

XArray

XArray 是一种抽象数据类型,类似于一个庞大的项目数组,其中每个项目都必须是 8 字节的对象,例如 Arc<T>Box<T>。用户存储的指针必须具有至少 4 字节的对齐方式。 XArray 促进了相邻条目的高效顺序访问,支持多路并发读取,并仅允许一次写入操作。

特性

  • 光标:提供对数组的精确和高效迭代的游标。游标有不可变和可变版本。可以同时持有多个不可变游标,或者一次仅持有可变游标。
  • 标记:提供标记条目和 XArray 自身的能力,以便于状态跟踪。
  • 泛型:通用实现,可以与任何适合用例的条目类型一起使用。
  • 写时复制(COW):在修改前有效地复制 XArray,并共享结构。

安装

将以下内容添加到您的 Cargo.toml

[dependencies]
xarray = "0.1.0"

使用

此 crate 在 no_std 环境中开发,但 std 用户仍然可以使用 --feature="std" 使用此 crate。

以下部分介绍了如何与 XArray 交互,包括创建 XArray、使用光标、标记、克隆等。


创建 XArray

// In std environment
extern crate alloc;

use alloc::sync::Arc;
use xarray::XArray;

// Create a new XArray instance
let mut xarray: XArray<Arc<i32>> = XArray::new();
  • 用户应声明存储在 XArray 中的项目(Arc)的类型,项目类型应实现 ItemEntry 特性。
  • 我们默认实现了 ItemEntry 对于 alloc::sync::Arcalloc::sync::Box,因此 std 用户可以直接使用它们。

使用游标

extern crate alloc;

use alloc::sync::Arc;
use xarray::XArray;

let mut xarray_arc: XArray<Arc<i32>> = XArray::new();

let mut cursor = xarray_arc.cursor_mut(0);
// Store the Arc at the index range 0~10000.
for i in 0..10000 {
    let value = Arc::new(i * 2);
    cursor.store(value);
    cursor.next();
}

cursor.reset_to(0);
for i in 0..10000 {
    let value = cursor.load().unwrap();
    assert!(*value.as_ref() == i * 2);
    cursor.next();
}

使用标记

以下是一个使用标记的示例,用于 XArray 中存储的页面,其中 PageMark 表示每个单独页面的状态

extern crate alloc;

use alloc::sync::Arc;
use xarray::{XArray, XMark, StdMutex};

#[derive(Clone, Copy)]

enum PageMark {
    DirtyPage 
    ...
}

impl From<PageState> for XMark {
    fn from(mark: PageState) -> Self {
        match mark {
            PageState::DirtyPage => Self::Mark0,
            ...
        }
    }
}

let mut pages: XArray<Page, StdMutex, PageState> = XArray::new();

let mut cursor = pages.cursor_mut(1000);
cursor.store(Page::alloc_zero());
// Mark the Page as DirtyPage.
cursor.set_mark(PageState::DirtyPage).unwrap();
assert!(cursor.is_marked(PageState::DirtyPage));
  • 项目和XArray默认可以有最多三个不同的标记,每个标记可以独立维护。
  • 用户需要使用一个结构体来表示需要使用的标记。对于需要多个标记的情况,这些标记通常封装在枚举类中。
  • 如果用户想要使用结构体M作为标记,他们应该为XMark实现From<M>特质,并在XArray的泛型列表中声明M

写时复制(COW)克隆

use std::sync::Arc;
use xarray::{XArray};

let mut xarray: XArray<Arc<i32>> = XArray::new();

// Store values
let value = Arc::new(10);
xarray.store(1, value.clone());
assert_eq!(*xarray.load(1).unwrap().as_ref(), 10);

// Clone the XArray
let mut xarray_clone = xarray.clone();
assert_eq!(*xarray_clone.load(1).unwrap().as_ref(), 10);

// Store a new value in the clone
let new_value = Arc::new(100);
xarray_clone.store(1, new_value);

// The original XArray is unaffected by changes in the clone
assert_eq!(*xarray.load(1).unwrap().as_ref(), 10);
assert_eq!(*xarray_clone.load(1).unwrap().as_ref(), 100);

迭代

use std::sync::Arc;
use xarray::XArray;

let mut xarray: XArray<Arc<i32>> = XArray::new();

// Store item to even index in the range 100~200.
for i in 100..200 {
    if i % 2 == 0 {
        let value = Arc::new(i * 2);
        cursor.store(value);
    }
    cursor.next();
}

// Iterate at the range 100~200.
let mut count = 0;
for item in xarray.range(100..200) {
    count += 1;
}
assert_eq!(count == 50);

许可证

XArray主要使用Mozilla公共许可证(MPL),版本2.0。

依赖关系

~74KB