这个问题在这里已经有了答案:
How do I create a global, mutable singleton?
(3 个回答)
How can you make a safe static singleton in Rust?
(3 个回答)
Recommended way to wrap C lib initialization/destruction routine
(2 个回答)
2年前关闭。
use std::sync::Once;
struct Store;
impl Store {
fn new() -> Store {
Store {
manifest: RwLock::new(/* ... */), // @note: RwLock does not implement Clone
}
}
fn save(&mut self) {
// ...
}
}
失败代码:
static mut store: Option<Store> = None;
static INIT: Once = Once::new();
unsafe {
INIT.call_once(|| {
store = Some(Store::new());
});
store.unwrap().save(); // Error: cannot move out of static item `store`
}
错误很简单,但这是我迫切需要完成的事情,因为
Store::new()
在后台进行了大量计算成本高昂的工作。我要求看似不可能的事情:声明类型为
Store
的静态变量并在运行时初始化它——假设 new
不能是 static
由于该函数内发生的绝对关键的内部可变性。此外,RwLock
是必需的,不能被克隆。我什至敢问这是否可以以线程安全的方式完成?没有推迟
new
函数调用或其内部属性作为我的程序中的后续函数调用(否则不相关)依赖于它。为了帮助使问题更清楚,这是在 FFI 的范围内。我对程序的生命周期或以更安全的方式管理此变量的能力没有太多控制权。虽然,我绝对想要这个
Store
变量在程序的生命周期内存活!我的问题是概念性的。我不希望这个确切的代码被稍微修改并突然编译。我在这里问一个问题,因为我无法理解如何实现我想要的。我尝试了其他几种方法……这是迄今为止我所做的最好的尝试。
最佳答案
如果没有 MCVE,很难确定你想要什么,但这是我设法做到的。
首先,正如编译器所说,您的问题非常简单:unwrap
消耗选项,你不能消耗静态。但是,您似乎真正想要的是就地改变商店,这是可能的,AFAIK 甚至以多种方式。
我选择的是跟随。一般来说,要就地改变某些东西,我们必须获得对它的独占引用。根据 Option 的文档,有 as_mut
method , 它转换 &mut Option<T>
进入 Option<&mut T>
.重要的部分是这个新选项是拥有的,即它不存储在静态中(而是引用静态),因此它可以被 unwrap
使用, 产生必要的 &mut
引用,我们可以在上面调用save
:
fn main() {
unsafe {
INIT.call_once(|| {
store = Some(Store::new());
});
store.as_mut().unwrap().save();
}
}
Playground可能实现您的目标。
但是,我不太确定您是否使用了
static mut
是有道理的。首先,完全不清楚为什么需要使用 &mut self
在 save
: 如果你只有 Store
是 RwLock
,您可以使用共享引用,因为这就是锁定的重点。在这种情况下,您可以简单地存储 Store
(双关语无意)在 lazy_static
:// skipping definitions
use lazy_static::lazy_static;
lazy_static! {
static ref store: Store = Store::new();
}
fn main() {
store.save();
}
Playground
关于rust - 使用不能声明为静态的函数在运行时初始化可变静态变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60409156/