gpt4 book ai didi

rust - 如何在 Rust 中制作安全的静态单例?

转载 作者:行者123 更新时间:2023-11-29 08:20:35 25 4
gpt4 key购买 nike

这是一个有争议的话题,所以让我先解释一下我的用例,然后再谈谈实际问题。

我发现对于一堆不安全的事情,重要的是要确保你不会泄漏内存;如果您开始使用 transmute()forget(),这实际上很容易做到。例如,将装箱实例传递给 C 代码任意时间,然后将其取回并使用 transmute 将其“复活”。

假设我有一个用于此类 API 的安全包装器:

trait Foo {}
struct CBox;

impl CBox {
/// Stores value in a bound C api, forget(value)
fn set<T: Foo>(value: T) {
// ...
}

/// Periodically call this and maybe get a callback invoked
fn poll(_: Box<Fn<(EventType, Foo), ()> + Send>) {
// ...
}
}

impl Drop for CBox {
fn drop(&mut self) {
// Safely load all saved Foo's here and discard them, preventing memory leaks
}
}

为了测试这实际上没有泄漏任何内存,我想要一些像这样的测试:

#[cfg(test)]
mod test {

struct IsFoo;
impl Foo for IsFoo {}
impl Drop for IsFoo {
fn drop(&mut self) {
Static::touch();
}
}

#[test]
fn test_drops_actually_work() {
guard = Static::lock(); // Prevent any other use of Static concurrently
Static::reset(); // Set to zero
{
let c = CBox;
c.set(IsFoo);
c.set(IsFoo);
c.poll(/*...*/);
}
assert!(Static::get() == 2); // Assert that all expected drops were invoked
guard.release();
}
}

如何创建这种类型的静态单例对象?

它必须使用Semaphore 风格的保护锁来确保多个测试不会同时运行,然后不安全地访问某种静态可变值。

我想也许this implementation would work , 但实际上它失败了,因为有时竞争条件会导致重复执行 init:

/// Global instance
static mut INSTANCE_LOCK: bool = false;
static mut INSTANCE: *mut StaticUtils = 0 as *mut StaticUtils;
static mut WRITE_LOCK: *mut Semaphore = 0 as *mut Semaphore;
static mut LOCK: *mut Semaphore = 0 as *mut Semaphore;

/// Generate instances if they don't exist
unsafe fn init() {
if !INSTANCE_LOCK {
INSTANCE_LOCK = true;
INSTANCE = transmute(box StaticUtils::new());
WRITE_LOCK = transmute(box Semaphore::new(1));
LOCK = transmute(box Semaphore::new(1));
}
}

请特别注意,与可以确定入口点 (main) 始终在单个任务中运行的普通程序不同,Rust 中的测试运行器不提供任何类型的单一入口点。

显然,除了指定最大任务数之外;给定几十个测试,只有少数需要做这种事情,而且只针对这种情况将测试任务池限制为一个是缓慢且毫无意义的。

最佳答案

它看起来像是 std::sync::Once 的用例:

use std::sync::{Once, ONCE_INIT};
static INIT: Once = ONCE_INIT;

然后在你的测试中调用

INIT.doit(|| unsafe { init(); });

Once保证您的 init只会执行一次,不管你调用多少次INIT.doit() .

关于rust - 如何在 Rust 中制作安全的静态单例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50336012/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com