小能豆

如何创建一个全局的、可变的单例?

rust

创建和使用系统中只有一个实例化的结构体的最佳方法是什么?是的,这是必要的,它是 OpenGL 子系统,制作它的多个副本并将其传递到各处会增加混乱,而不是缓解混乱。

单例需要尽可能高效。似乎不可能在静态区域上存储任意对象,因为它包含Vec带有析构函数的对象。第二个选项是在静态区域上存储一个(不安全)指针,指向堆分配的单例。在保持语法简洁的同时,最方便、最安全的方法是什么?


阅读 75

收藏
2024-05-21

共1个答案

小能豆

在 Rust 中创建只有一个实例的结构体最常见的方法是使用 lazy_static crate 来实现惰性静态初始化。这样可以确保结构体只会在首次访问时被初始化,并且在整个程序运行期间只会初始化一次。

下面是一个示例,演示了如何使用 lazy_static crate 创建单例结构体:

首先,将 lazy_static crate 添加到你的 Cargo.toml 文件中:

[dependencies]
lazy_static = "1.4"

然后,你可以按照以下方式在代码中使用:

use lazy_static::lazy_static;
use std::sync::Mutex;

// 定义一个结构体,用于存储 OpenGL 子系统的状态或数据
struct OpenGLSubsystem {
    // 这里可以包含你需要的任何状态或数据
}

// 使用 lazy_static 宏定义一个静态的 Mutex,用于包裹 OpenGLSubsystem 结构体的可变引用
lazy_static! {
    static ref OPENGL_SUBSYSTEM: Mutex<OpenGLSubsystem> = Mutex::new(OpenGLSubsystem { /* 初始化状态或数据 */ });
}

// 现在,你可以在代码的任何地方通过访问 OPENGL_SUBSYSTEM 获取 OpenGL 子系统的实例
fn main() {
    // 获取 OpenGL 子系统的实例
    let mut opengl = OPENGL_SUBSYSTEM.lock().unwrap();

    // 现在你可以在 opengl 上调用方法,对其进行操作
    // 例如:
    // opengl.some_method();

    // 注意:由于 OPENGL_SUBSYSTEM 是一个 Mutex,需要在使用之前获取锁
    // 使用完毕后,锁会在作用域结束时自动释放
}

在上面的代码中,OPENGL_SUBSYSTEM 是一个 Mutex 包裹的 OpenGLSubsystem 结构体的静态变量。通过 lazy_static! 宏,我们确保 OPENGL_SUBSYSTEM 只会在首次访问时被初始化,而且在整个程序运行期间只会初始化一次。在使用之前,我们需要获取 OPENGL_SUBSYSTEM 的锁,并在作用域结束时释放锁。

2024-05-21