8 个版本 (2 个稳定版)

使用旧的 Rust 2015

1.0.1 2018 年 9 月 28 日
0.4.2 2018 年 9 月 25 日
0.3.0 2018 年 9 月 6 日
0.2.0 2018 年 9 月 5 日
0.1.0 2018 年 8 月 19 日

#632 in 内存管理

每月 22 次下载

MIT/Apache

15KB
338

宝库

文档

可克隆和合并的线程本地竞技场分配器。

宝库设计为用于不可变数据结构的灵活分配器和动态借用检查器。

竞技场将每个附加的值存储在固定的内存位置中,并且只一次性释放它们。这是通过使用多个支持向量的数组来实现的,这些向量按长度递增排列,如下所示

克隆和合并

竞技场可以被克隆和合并,这是通过顶层 Arena 类型是映射递增 id 到子竞技场的 VecMap 来实现的。当一个竞技场被克隆时,将创建 两个 新的子竞技场,并赋予它们两个新的 id。

如果通过旧竞技场的引用请求可变借用,无论是从克隆的竞技场中的任何一个,都会克隆并放入新的子竞技场中,这样旧的引用仍然有效。

#[test]
fn clone() {
    let arena_a = Arena::new();

    let a = arena_a.append(0);
    let mut b = arena_a.append(1);

    // c is cloned from b, since mutably accesing b makes it point to its
    // new memory location.
    let c = b.clone();

    assert_eq!(*arena_a.get(&a), 0);
    assert_eq!(*arena_a.get(&b), 1);

    let arena_b = arena_a.clone();

    // change the value in arena_a
    *arena_a.get_mut(&mut b) += 1;

    // value changed
    assert_eq!(*arena_a.get(&b), 2);

    // old reference `c` is still pointing to the unmodified entry
    assert_eq!(*arena_b.get(&c), 1);
}

#[test]
fn merge() {
    let arena_a = Arena::new();
    let arena_b = Arena::new();

    let a = arena_a.append(0);
    let b = arena_b.append(1);

    // merge the arenas into one, leaving both `a` and `b` accessible
    // through `arena_c`

    let arena_c = Arena::merge(&arena_a, &arena_b);

    assert_eq!(*arena_c.get(&a), 0);
    assert_eq!(*arena_c.get(&b), 1);
}

内存布局

每个子竞技场的内存布局排列如下

[0, 1]
[2, 3, 4, 5]
[6, 7, 8, 9, 10, 11, 12, 13]

此实现使用第一行向量的大小为 32,并将加倍向量按 32 行排列。

这确保了不可能重新分配和移动条目,并允许我们从竞技场的不可变借用安全地创建一个 RefMut

依赖项

~90KB