3 个版本

0.1.2 2022年2月7日
0.1.1 2020年1月5日
0.1.0 2019年10月25日

#693内存管理

34 每月下载量

MIT/Apache

8KB
68 代码行

Quickdry

License Cargo Documentation

此 crate 提供基于跳转指针的分配区分配。

许可证

许可协议为以下之一:

任选其一。

贡献

除非您明确声明,否则根据 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);
}

无运行时依赖