# XArray `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` or `Box`. 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. ## Features - **Cursors:** Provide cursors for precise and efficient iteration over the array. Cursors have both immutable and mutable versions. One can hold multiple immutable cursors or hold a mutable cursor exclusively at a time. - **Marking:** Provide ability to mark entries and the XArray itself for easy state tracking. - **Generics:** Generic implementation that can work with any entry type and any inner locks that fits the use case. - **Copy-on-Write (COW):** Efficient cloning of XArrays with shared structure until mutation. ## Installation Add this to your `Cargo.toml`: ```toml [dependencies] xarray = "0.1.0" ``` ## Usage 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. ### Creating an `XArray`: - Users should declare the type of items (Arc) stored in the XArray and the lock (StdMutex) used inside the XArray. Note that `StdMutex` is an abstraction for `std::sync::Mutex`. - The type of stored item must implement `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 ```rust extern crate alloc; use alloc::sync::Arc; use xarray::{XArray, StdMutex}; // Create a new XArray instance let mut xarray: XArray, StdMutex> = XArray::new(); ``` ### Using Cursor ```rust extern crate alloc; use alloc::sync::Arc; use xarray::{XArray, StdMutex}; let mut xarray_arc: XArray, 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(); } ``` ### Using Marks - Items and the `XArray` can have up to three distinct marks by default, with each mark independently maintained. - Users need to use a struct to represent the marks that need to be used. For the situation where multiple marks are required, these marks are typically encapsulated within an enumeration class. - This struct for marks should implement `Into` trait and be declared in the generics list of XArray. ```rust extern crate alloc; use alloc::sync::Arc; use xarray::{XArray, XMark, StdMutex}; #[derive(Clone, Copy)] enum MarkDemo { Mark0, Mark1, Mark2, } impl Into 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, 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)); ``` ### Copy-On-Write (COW) Clone ```rust use std::sync::Arc; use xarray::{XArray, StdMutex}; let mut xarray: XArray, 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); ``` ### Iteration ```rust use std::sync::Arc; use xarray::{XArray, StdMutex}; let mut xarray: XArray, 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); ``` ## License