3 个版本
0.1.2 | 2022年2月7日 |
---|---|
0.1.1 | 2020年1月5日 |
0.1.0 | 2019年10月25日 |
#693 在 内存管理
34 每月下载量
8KB
68 代码行
Quickdry
此 crate 提供基于跳转指针的分配区分配。
许可证
许可协议为以下之一:
- Apache License, Version 2.0 (LICENSE-APACHE 或 https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT License (LICENSE-MIT 或 https://apache.ac.cn/licenses/LICENSE-2.0)
任选其一。
贡献
除非您明确声明,否则根据 Apache-2.0 许可证定义的,任何有意提交以包含在作品中的贡献,都将双重许可,如上所述,无需任何附加条款或条件。
lib.rs
:
Quickdry
Quickdry 是一个用于分配区分配的库。
分配区保持指向大块内存的单个指针。分配非常快,因为它只是将指针向前移动,不维护单个分配的元数据。作为交换,分配区中的所有内存必须一次性释放。
例如,类似于 Linux 内核风格的循环双链表
use core::{ptr, cell::Cell};
use core::alloc::Layout;
use quickdry::Arena;
#[repr(C)]
pub struct Node<'a> {
pub data: i32,
pub next: Cell<&'a Node<'a>>,
pub prev: Cell<&'a Node<'a>>,
}
impl<'a> Node<'a> {
pub fn in_arena(arena: &'a Arena, data: i32) -> &'a Self {
#[repr(C)]
struct NodeUninit<'a> {
data: i32,
next: Cell<Option<&'a NodeUninit<'a>>>,
prev: Cell<Option<&'a NodeUninit<'a>>>,
}
unsafe {
let ptr = arena.alloc(Layout::new::<Self>()) as *mut Self;
let bootstrap = ptr as *mut NodeUninit<'a>;
let next = Cell::new(None);
let prev = Cell::new(None);
ptr::write(bootstrap, NodeUninit { data, next, prev });
let node = &*bootstrap;
node.next.set(Some(node));
node.prev.set(Some(node));
&*ptr
}
}
pub fn add_head(&'a self, new: &'a Self) { Self::insert(new, self, self.next.get()) }
pub fn add_tail(&'a self, new: &'a Self) { Self::insert(new, self.prev.get(), self) }
pub fn del(&'a self) { Self::remove(self.prev.get(), self.next.get()) }
fn insert(new: &'a Self, prev: &'a Self, next: &'a Self) {
next.prev.set(new);
new.next.set(next);
new.prev.set(prev);
prev.next.set(new);
}
fn remove(prev: &'a Self, next: &'a Self) {
next.prev.set(prev);
prev.next.set(next);
}
}
fn main() {
let arena = Arena::default();
let list = Node::in_arena(&arena, 3);
list.add_head(Node::in_arena(&arena, 5));
list.add_tail(Node::in_arena(&arena, 8));
assert_eq!(list.data, 3);
assert_eq!(list.next.get().data, 5);
assert_eq!(list.next.get().next.get().data, 8);
assert_eq!(list.next.get().next.get().next.get().data, 3);
list.next.get().del();
assert_eq!(list.data, 3);
assert_eq!(list.next.get().data, 8);
assert_eq!(list.next.get().next.get().data, 3);
}