2

我是将熟悉的 Cpp 项目翻译成 Rust 的初学者。该项目包含一个名为 Globals 的类,它存储全局配置参数。以下是其 cpp 文件的摘录:

static Globals &__get()
{
  static Globals globals;
  return globals;
}

const Globals &Globals::get()
{
  auto &globals = __get();
  if (!globals.initialized) {
    throw std::runtime_error("Initialize globals first");
  }
  return globals;
}

void Globals::set(const Globals &globals)
{
  __get() = globals;
}

我如何将它翻译成 Rust?据我所知__get()实现了某种单例逻辑。我已经阅读了有关lazy_static crate 以实现类似的东西,但是每次我想读取它的值时解锁变量似乎太冗长了。是否可以在 cpp 代码中使用诸如Globals::get()之类的接口来实现这一点。

我很少发帖,所以如果我忘记了什么,请告诉我,我会提供详细信息。谢谢!

4

2 回答 2

3

我已经阅读了有关lazy_static crate 以实现类似的东西,但是每次我想读取它的值时解锁变量似乎太冗长了。

有一个很好的理由:“安全生锈”包括您所谓的线程安全设计。一个不受保护的可变全局是非常不安全的。

这......这就是为什么与可变静态交互需要unsafe(无论是阅读还是写作)。

从 C++ 的翻译非常简单 [0] 并且可以很容易地从statics 的参考部分推断出来,唯一真正的分歧是必须初始化 Rust 静态。

另请注意,如果您不需要突变,那么您可以lazy_static!一个只读值(您根本不需要互斥锁),并且不需要解锁任何东西。

[0] 虽然通过消除不必要的东西而大大简化了__get

于 2020-10-15T11:21:19.060 回答
1

Rust 要求安全代码中的内存安全——因此,您不能在安全代码中使用可变静态。你可以有一个原子静态(参见AtomicBoolAtomicU64的例子),但对于一个普通类型,你将需要某种锁定机制,例如RwLockMutex(如果性能是你的事,parking_lot crate 提供更多性能的实现比 Rust 标准库)

如果您不想自己处理锁定,我可以建议使用 getter/setter 方法制作一个包装器对象吗?

use std::sync::{Arc, RwLock};
use once_cell::sync::Lazy;

static GLOBAL: Lazy<Global> = Lazy::new(Global::new);

struct GlobalThingymajig {
    pub number: u32,
    pub words: String,
}

pub struct Global(Arc<RwLock<GlobalThingymajig>>);

impl Global {
    pub fn new() -> Self {
        Self(Arc::new(RwLock::new(
            GlobalThingymajig {
                number: 42,
                words: "The Answer to Life, The Universe, and Everything".into()
            }
        )))
    }

    pub fn number(&self) -> u32 {
        self.0.read().unwrap().number
    }

    pub fn words(&self) -> String {
        self.0.read().unwrap().words.clone()
    }

    pub fn set_number(&self, new_number: u32) {
        let mut writer = self.0.write().unwrap();
        writer.number = new_number;
    }

    pub fn set_words(&self, new_words: String) {
        let mut writer = self.0.write().unwrap();
        writer.words = new_words;
    }
}

您可以在此处的 Rust Playground 上看到此示例

于 2020-10-15T22:42:21.633 回答