2 个不稳定版本

0.2.0 2020 年 6 月 5 日
0.1.0 2020 年 2 月 2 日

#1067 in 并发

每月 25 次下载

MIT 许可证

38KB
657

refptr

Latest Version Documentation Build Status

Rust 中侵入式引用计数结构体的宏、属性和特性。请参阅文档以获取更多信息。


lib.rs:

Rust 中侵入式引用计数结构体的宏、属性和特性。

该crate围绕操作侵入式引用计数结构体而构建。这些结构体使用 #[refcounted] 属性声明,使用 make_refptr 宏构造,并使用 RefPtrWeakPtr 智能指针类型管理其生命周期。

声明引用计数结构体

可以将 #[refcounted] 属性应用于 struct 声明,以将其标记为引用计数。引用计数结构体始终在堆上分配,并使用 make_refptr 辅助宏构造。

示例

#[refcounted(local)]
struct HeapInteger {
    value: Cell<i32>,
}

let orig = make_refptr!(HeapInteger { value: Cell::new(10) });
let copy = orig.clone();
orig.value.set(20);
assert_eq!(copy.value.get(), 20);

分配

使用 #[refcounted] 声明的结构体使用 make_refptr! 宏在堆上构造。此宏接受结构体字面量语法,但将值构造在堆上。

这是为了确保类型始终在堆上以进行侵入式引用计数。

示例

let ptr = make_refptr!(HeapPair { t: 10, u: 20 });
assert_eq!(ptr.t, 10);
assert_eq!(ptr.u, 20);

终止和 Drop

使用 #[refcounted] 注释的类型不能手动实现 Drop,因为这会在对象正在释放时允许恢复 RefPtr<Self>,从而导致使用后释放。

如果需要最终化方法,则#[refcounted(finalize)]属性提供了对自定义最终化的支持。如果启用了最终化,则在丢弃任何字段之前会调用一个fn finalize(&self)方法。

finalize方法执行期间,代码可能获得一个新的强引用,这可能导致在返回后结构体不会被丢弃。因此,finalize可能在结构体的整个生命周期中被多次调用。

配置

#[refcounted(atomic)]#[refcounted(local)]

在类似Arc的原子引用计数或类似Rc的线程本地引用计数之间进行选择。只要所有字段都可以共享,原子引用计数的类型可以在线程之间共享。

必须指定引用计数的原子性。

示例

#[refcounted(atomic)]
struct HeapInt { i: i32 }

let here = make_refptr!(HeapInt { i: 10 });
let thread = thread::spawn(move || here.i);
assert_eq!(thread.join().unwrap(), 10);

#[refcounted(weak)]

添加了对弱引用计数和WeakPtr智能指针类型的支持。此注释可以与其他注释结合使用。

示例

#[refcounted(atomic, weak)]
struct HeapInt { i: i32 }

let here = make_refptr!(HeapInt { i: 10 });
let weak = WeakPtr::new(&*here);
assert_eq!(weak.upgrade().unwrap().i, 10);
drop(here);
assert!(weak.upgrade().is_none());

#[refcounted(finalize)]

在尝试销毁结构体之前,会在结构体上调用一个fn finalize(&self)方法。有关详细信息,请参阅“最终化”部分。此注释可以与其他注释结合使用。

支持使用RefPtr引用的结构体会被标记为具有#[refcounted(...)]属性。此属性会生成所需的非安全代码、额外成员和特质实现。

#[refcounted(atomic, finalize)]
struct FinalizeExample {}

static FINALIZED: AtomicBool = AtomicBool::new(false);
impl FinalizeExample {
    fn finalize(&self) {
        FINALIZED.store(true, SeqCst);
    }
}

let orig = make_refptr!(FinalizeExample {});
assert_eq!(FINALIZED.load(SeqCst), false);
let copy = orig.clone();
assert_eq!(FINALIZED.load(SeqCst), false);
drop(orig);
assert_eq!(FINALIZED.load(SeqCst), false);
drop(copy);
assert_eq!(FINALIZED.load(SeqCst), true);

特质对象

#[refcounted]也可以用于管理特质对象的生命周期,通过在特质对象的层次结构中包含Refcounted特质。需要指定关联类型Rc以保持对象安全。

refcnt模块包含此crate使用的特定引用计数类型。

示例

trait MyTrait : Refcounted<Rc = refcnt::AtomicWeak> {
    fn my_trait_method(&self) -> i32;
}

#[refcounted(atomic, weak)]
struct MyStruct { i: i32 }

impl MyTrait for MyStruct {
    fn my_trait_method(&self) -> i32 { self.i }
}

fn takes_trait_object(obj: &dyn MyTrait) -> i32 {
    let strong_ref: RefPtr<dyn MyTrait> = RefPtr::new(obj);
    strong_ref.my_trait_method()
}

let concrete = make_refptr!(MyStruct { i: 10 });
let i = takes_trait_object(&*concrete);
assert_eq!(i, 10);

依赖项

~1.5MB
~34K SLoC