#gc #垃圾 #垃圾收集 #收集

bronze_derive

bronze_gc 的 Trace 和 Finalize 特性推导插件

2 个不稳定版本

0.1.0 2021年4月11日
0.0.1 2021年3月26日

#38#垃圾


用于 bronze_gc

MPL-2.0 许可证

4KB
50

Bronze

安装

要使用 Bronze,您必须使用 Rust 的夜间工具。要安装它们,请在命令行中运行 rustup default nightly

使用方法

有时,Rust 中所有权的约束可能难以处理。例如,在 Rust 中实现双向链表非常困难,因为每个节点都必须被引用两次。此外,特别是对于正在学习 Rust 的人来说,暂时避免“每个变量只有一个所有者”的约束可能更容易。

Bronze 通过引入一种新的智能指针类型 GcRef,放宽了 Rust 的某些约束,GcRef 描述了一个指向垃圾回收堆位置的指针。使用 Bronze 时,位于 堆栈 上的数据具有所有常见的 Rust 所有权要求。然而,Bronze 允许将数据移动到 。如果类型 T 的值位于堆上,Bronze 允许多个 GcRef<T> 类型的引用指向该值。

例如,没有 Bronze,我们必须仔细管理引用和生存期

pub struct IntContainer {
    n: i32,
}

pub fn set(c: &mut IntContainer, n: i32) {
    c.n = n;
}

pub fn test() {
    let c1 = IntContainer{n: 42};
    let mut c2 = c1;
    
    // Can't use c1 anymore because it's been moved to c2
    set(&mut c2, 42);
}

使用 Bronze,非 Copy 类型的类型可以通过智能指针自由引用,这些智能指针 Copy

// 
#[derive(Trace, Finalize)]
pub struct IntContainer {
    n: i32,
}

pub fn set(mut c: GcRef<IntContainer>, n: i32) {
    c.n = n;
}

pub fn test() {
    let c1 = GcRef::new(IntContainer{n: 42});
    let c2 = c1; 
    // Now c1 and c2 both reference the same object.
    
    set(c2, 42);
    set(c1, 43);
    // Now they both reference an object with value 43.
}

因为 GcRef 实现了 Deref,并且因为 Rust 会自动在需要时插入 *,所以您可以通常将 GcRef<T> 视为直接是 T。例如,在上面的 set() 中,主体将值赋给 c.n。这隐含地意味着要取消引用指针并将值赋给引用值内部的 n。如果您愿意,您也可以调用 as_ref()as_mut() 来获取 GC 堆中数据的引用或可变引用。

要创建一个新的 GcRef<T>,请调用 GcRef::new(e),其中 e 是你希望存在于 GC 堆上的值的表达式。

高级用法

如果你需要从 GC 堆中删除数据,可以使用 GcNullableRef 而不是 GcRef。你可以使用 Gc::new_nullable 来创建一个。 GcNullableRefGcRef 类似,但增加了一个 remove 方法。第一次调用 remove 会返回一个填充有之前在 GC 堆中数据的 Option。后续调用 remove 返回 None。

实验性实现

此实现是 实验性的。特别是,收集器将不会运行;请注意,你最终会耗尽内存。然而,当前版本适合实验和原型设计。

依赖关系

~1.5MB
~38K SLoC