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>
.
User-stored pointers must have a minimum alignment of 4 bytes. XArray
facilitates efficient sequential access to adjacent entries,
supporting multiple concurrent reads and exclusively allowing one write operation at a time.
Add this to your Cargo.toml
:
[dependencies]
xarray = "0.1.0"
This crate is developed in no_std
environment, but std users can still use this crate with --feature="std"
:
The following section covers how to interact with XArray
including creating an XArray
, using cursors, marking, cloning, and more.
XArray
:StdMutex
is an abstraction for std::sync::Mutex
.
ItemEntry
trait and the used lock abstraction must be generated by the macro abstract_lock_to!
. The real lock type that be abstracted should implement ValidLock
trait.We implement ItemEntry
for alloc::sync::Arc
and alloc::sync::Box
by default, and abstract std::sync::Mutex
and std::sync::RwLock
as StdMutex
and StdRwLock
for std users, respectively
extern crate alloc;
use alloc::sync::Arc;
use xarray::{XArray, StdMutex};
// Create a new XArray instance
let mut xarray: XArray<Arc<i32>, StdMutex> = XArray::new();
extern crate alloc;
use alloc::sync::Arc;
use xarray::{XArray, StdMutex};
let mut xarray_arc: XArray<Arc<i32>, StdMutex> = 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
can have up to three distinct marks by default, with each mark independently maintained.This struct for marks should implement Into<XMark>
trait and be declared in the generics list of XArray.
extern crate alloc;
use alloc::sync::Arc;
use xarray::{XArray, XMark, StdMutex};
#[derive(Clone, Copy)]
enum MarkDemo {
Mark0,
Mark1,
Mark2,
}
impl Into<XMark> for MarkDemo {
fn into(self) -> XMark {
match self {
MarkDemo::Mark0 => XMark::Mark0,
MarkDemo::Mark1 => XMark::Mark1,
MarkDemo::Mark2 => XMark::Mark2,
}
}
}
let mut xarray_arc: XArray<Arc<i32>, StdMutex, MarkDemo> = XArray::new();
// Mark the xarray with Mark1.
xarray_arc.set_mark(MarkDemo::Mark0);
assert!(xarray_arc.is_marked(MarkDemo::Mark0));
let mut cursor = xarray_arc.cursor_mut(1000);
let value = Arc::new(i * 2);
cursor.store(value);
// Mark the item with Mark1.
cursor.set_mark(MarkDemo::Mark1).unwrap();
assert!(cursor.is_marked(MarkDemo::Mark1));
use std::sync::Arc;
use xarray::{XArray, StdMutex};
let mut xarray: XArray<Arc<i32>, StdMutex> = XArray::new();
// Store values
let value = Arc::new(10);
xarray.store(333, value.clone());
assert_eq!(*xarray.load(333).unwrap().as_ref(), 10);
// Clone the XArray
let mut xarray_clone = xarray.clone();
assert_eq!(*xarray_clone.load(333).unwrap().as_ref(), 10);
// Store a new value in the clone
let new_value = Arc::new(100);
xarray_clone.store(333, new_value);
// The original XArray is unaffected by changes in the clone
assert_eq!(*xarray.load(333).unwrap().as_ref(), 10);
assert_eq!(*xarray_clone.load(333).unwrap().as_ref(), 100);
use std::sync::Arc;
use xarray::{XArray, StdMutex};
let mut xarray: XArray<Arc<i32>, StdMutex> = 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);