mtb_entity_slab/
lib.rs

1//! # MTB Entity Allocator and Utilities
2//!
3//! Address-stable, internally mutable entity Slab allocator. Mainly solves the problem
4//! where `Slab` cannot allocate new elements while reading existing ones.
5//!
6//! 地址稳定、内部可变的实体 Slab 分块分配器. 主要解决 `Slab` 无法在读取元素的同时
7//! 分配新元素的问题.
8//!
9//! ## Example 使用示例
10//!
11//! ```
12//! use mtb_entity_slab::{EntityAlloc, PtrID, IEntityAllocID, IEntityAllocatable, EntityAllocPolicy256};
13//!
14//! #[derive(Debug, Clone, PartialEq, Eq)]
15//! #[mtb_entity_slab::entity_allocatable]
16//! struct Inst {
17//!     pub opcode: u32,
18//!     pub operands: [u64; 4],
19//!     pub heap_data: String,
20//! }
21//! /*
22//!   The annotation above is equivalent to the following code:
23//!   上面的注解相当于下面的代码:
24//!
25//!   impl IEntityAllocatable for Inst {
26//!       /// Allocation policy type. You can switch types from 128 to 4096 bytes.
27//!       /// 分配策略类型. 可在 128 到 4096 字节间切换.
28//!       type AllocatePolicyT = EntityAllocPolicy256<Self>;
29//!
30//!       /// Pointer ID type. You can define your own PtrID type if needed.
31//!       /// 指针 ID 类型. 如有需要, 可自定义 PtrID 类型.
32//!       type PtrID = PtrID<Self>;
33//!   }
34//! */
35//!
36//! impl Inst {
37//!     fn new(opcode: u32) -> Self {
38//!         Self {
39//!             opcode,
40//!             operands: [0; 4],
41//!             heap_data: format!("InstData{}", opcode),
42//!         }
43//!     }
44//! }
45//!
46//! fn main() {
47//!     let mut alloc = EntityAlloc::with_capacity(1024);
48//!     let ptrs = {
49//!         let mut v = Vec::new();
50//!         for i in 0..1000 {
51//!             let ptr = alloc.allocate(Inst::new(i));
52//!             v.push(ptr);
53//!         }
54//!         v
55//!     };
56//!
57//!     let inst = ptrs[500].deref(&alloc);
58//!
59//!     // Allocates a new element while reading existing ones
60//!     // 在读取时分配新元素
61//!     let new_id = alloc.allocate(Inst::new(2000));
62//!     assert_eq!(inst.opcode, 500);
63//!     assert_eq!(new_id.deref(&alloc).opcode, 2000);
64//!
65//!     for &ptr in ptrs.iter() {
66//!         let inst = ptr.deref(&alloc);
67//!         let indexed_id = ptr.as_indexed(&alloc).unwrap();
68//!         assert_eq!(inst.opcode as usize, indexed_id.0);
69//!         assert!(ptr.free(&mut alloc).is_some());
70//!     }
71//! }
72//! ```
73//!
74//! ## Safety 安全性
75//!
76//! This crate provides access to allocated elements via `PtrID`. `PtrID` contains a raw pointer,
77//! and most operations on `PtrID` are safe, but there is no ABA usage detection.
78//!
79//! This crate is designed for Remusys-IR and is for learning purposes only. It does not guarantee
80//! safety in all scenarios. Please carefully assess the risks when using it in production environments.
81//!
82//! 本库通过 `PtrID` 提供对分配元素的访问. `PtrID` 内部包含裸指针, 对 PtrID 的大多数操作都是安全的,
83//! 但没有 ABA 使用检测.
84//!
85//! 本库为 Remusys-IR 设计, 仅为学习用途, 不保证在所有场景下的安全性. 在生产环境中使用时请谨慎评估风险.
86
87mod alloc;
88mod bitalloc;
89mod chunk;
90mod container;
91mod id;
92mod iter;
93mod policy;
94
95pub use crate::{
96    alloc::{EntityAlloc, IEntityAllocatable},
97    chunk::NULL_INDEXED_ID,
98    container::ptrlist::*,
99    id::{IDProxy, IEntityAllocID, IndexedID, PtrID},
100    iter::{EntityAllocConsumeIter, EntityAllocEditIter, EntityAllocReadIter},
101    policy::*,
102};
103pub use mtb_entity_slab_macros::entity_allocatable;
104
105pub const MTBLIB_PACKAGE_NAME: &str = "io.medihbt.mtb.entity";
106pub const MTBLIB_PACKAGE_VERSION: &str = env!("CARGO_PKG_VERSION");
107
108mod tests;