13个不稳定版本 (3个破坏性更改)
0.4.0 | 2023年12月24日 |
---|---|
0.3.5 | 2023年11月24日 |
0.2.2 | 2023年11月14日 |
0.1.2 | 2023年9月18日 |
208 在 内存管理 中排名 #208
152 每月下载
用于 2 crate
110KB
2.5K SLoC
zone-alloc
此crate提供基于区域(也称为基于区域或基于竞技场)的数据分配的数据类型。区域分配是一种内存管理类型,其中分配的对象被分配到特定的区域。区域中的数据在区域的生命周期内保持有效和可用,并在使用后一起释放区域中的所有数据。
此crate还提供“注册表”,这是一种提供竞技场分配元素和内部可变性的容器类型,具有简单的运行时借用检查。
[dependencies]
zone-alloc = "0.3"
用法
此crate定义了三个容器
Arena<T>
- 可以用于分配特定类型值的竞技场分配容器。Registry<T>
-Arena<T>
的扩展,提供分配数据的整数句柄。StrongRegistry<H, T>
-Registry<T>
的扩展,提供分配数据的强类型句柄。KeyedArena<K, T>
-Arena<T>
的扩展,维护键到值的映射。
其他Crates
zone-alloc-strong-handle-derive
- 当与StrongRegistry
一起工作时,在简单的Handle
类型包装器上生成StrongHandle
接口的过程宏。
功能
虽然crate默认使用Rust标准库构建,但可以移除此功能以用于无std环境。
default
-std
std
- 依赖于Rust标准库。may-dangle
- 在#[may_dangle]
属性上使用Drop
实现的ElementRef
和ElementRefMut
。
示例
使用 Arena<T>
的链表节点
use zone_alloc::Arena;
#[derive(Debug, PartialEq, Eq)]
struct Node<'a, T> {
parent: Option<&'a Node<'a, T>>,
value: T,
}
impl<'a, T> Node<'a, T> {
pub fn new(parent: Option<&'a Node<'a, T>>, value: T) -> Self {
Self { parent, value }
}
}
fn main() {
let arena = Arena::new();
let node = arena.alloc(Node::new(None, 1));
let node = arena.alloc(Node::new(Some(node), 2));
let node = arena.alloc(Node::new(Some(node), 3));
assert_eq!(node.value, 3);
assert_eq!(node.parent.unwrap().value, 2);
assert_eq!(node.parent.unwrap().parent.unwrap().value, 1);
assert_eq!(node.parent.unwrap().parent.unwrap().parent, None);
}
使用 Registry<T>
的循环引用
use zone_alloc::{
Handle,
Registry,
};
#[derive(Debug, PartialEq, Eq)]
struct Node<T> {
parent: Option<Handle>,
value: T,
}
impl<T> Node<T> {
pub fn new(parent: Option<Handle>, value: T) -> Self {
Self { parent, value }
}
}
fn main() {
let registry = Registry::new();
let root_handle = registry.register(Node::new(None, "first"));
let handle = registry.register(Node::new(Some(root_handle), "second"));
let handle = registry.register(Node::new(Some(handle), "third"));
registry.get_mut_unchecked(root_handle).parent = Some(handle);
let node = registry.get(handle).unwrap();
assert_eq!(node.value, "third");
let node = registry.get(node.parent.unwrap()).unwrap();
assert_eq!(node.value, "second");
let node = registry.get(node.parent.unwrap()).unwrap();
assert_eq!(node.value, "first");
let node = registry.get(node.parent.unwrap()).unwrap();
assert_eq!(node.value, "third");
}
使用 KeyedRegistry<T>
的循环引用
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(not(feature = "std"))]
use alloc::borrow::ToOwned;
use zone_alloc::KeyedRegistry;
#[derive(Debug, PartialEq, Eq)]
struct Node<K, V> {
parent: Option<K>,
value: V,
}
impl<K, V> Node<K, V> {
pub fn new(parent: Option<K>, value: V) -> Self {
Self { parent, value }
}
}
fn main() {
let registry = KeyedRegistry::new();
registry.register("node-1".to_owned(), Node::new(None, "first"));
registry.register(
"node-2".to_owned(),
Node::new(Some("node-1".to_owned()), "second"),
);
registry.register(
"node-3".to_owned(),
Node::new(Some("node-2".to_owned()), "third"),
);
registry.get_mut_unchecked("node-1").parent = Some("node-3".to_owned());
let node = registry.get("node-3").unwrap();
assert_eq!(node.value, "third");
let node = registry.get(node.parent.as_ref().unwrap()).unwrap();
assert_eq!(node.value, "second");
let node = registry.get(node.parent.as_ref().unwrap()).unwrap();
assert_eq!(node.value, "first");
let node = registry.get(node.parent.as_ref().unwrap()).unwrap();
assert_eq!(node.value, "third");
}
运行时借用检查
use zone_alloc::{
BorrowError,
Registry,
};
fn main() {
let registry = Registry::new();
registry.register_extend(100..200);
// Multiple immutable borrows on the same element.
let borrow_1 = registry.get(16);
let borrow_2 = registry.get(16);
let borrow_3 = registry.get(16);
assert!(borrow_1.as_ref().is_ok_and(|i| i.eq(&116)));
assert!(borrow_2.as_ref().is_ok_and(|i| i.eq(&116)));
assert!(borrow_3.as_ref().is_ok_and(|i| i.eq(&116)));
// Mutable borrow fails.
assert_eq!(
registry.get_mut(16).err(),
Some(BorrowError::AlreadyBorrowed)
);
// Another element can be borrowed independently.
let borrow_4 = registry.get(32);
assert!(borrow_4.as_ref().is_ok_and(|i| i.eq(&132)));
assert!(borrow_1.as_ref().is_ok_and(|i| i.eq(&116)));
// Only one mutable borrow allowed.
let mut borrow_5 = registry.get_mut(64).unwrap();
assert!(borrow_5.eq(&164));
*borrow_5 *= 2;
assert!(borrow_5.eq(&328));
assert_eq!(
registry.get_mut(64).err(),
Some(BorrowError::AlreadyBorrowed)
);
assert_eq!(registry.get(64).err(), Some(BorrowError::AlreadyBorrowed));
// Refetch to show updated value, and show that previous borrows are still valid.
drop(borrow_5);
let borrow_5 = registry.get(64);
assert!(borrow_5.as_ref().is_ok_and(|i| i.eq(&328)));
assert!(borrow_4.as_ref().is_ok_and(|i| i.eq(&132)));
assert!(borrow_1.as_ref().is_ok_and(|i| i.eq(&116)));
}
依赖
~2MB
~25K SLoC