我的问题如下:
是否可以对对象进行延迟初始化,然后将其借用为'static
终生可变的?
一些上下文
首先,我将展示一个示例来说明延迟初始化的含义。我提出的延迟初始化模型是将 cratelazy_static
与一个标准库一起使用,其中包含Mutex
一个Option<T>
. 这里有一个延迟初始化的例子。
use lazy_static::lazy_static;
use std::thread::JoinHandle;
use std::sync::Mutex;
pub struct DeferredStruct {
internal_field: u32,
}
impl DeferredStruct {
pub fn new(internal_field: u32) -> Self {
Self {
internal_field,
}
}
pub fn regular_function(&mut self) {
self.internal_field += 1;
println!("{}", self.internal_field);
}
}
lazy_static! {
static ref MY_DEFERRED: Mutex<Option<DeferredStruct>> = Mutex::new(None);
}
fn main() {
// Initial processing
// ...
// ...
// The value 10 would be obtained from a configuration file on runtime.
let deferred_struct = DeferredStruct::new(10);
let mut lock = MY_DEFERRED.lock().unwrap();
lock.replace(deferred_struct);
std::mem::drop(lock); // In this example we drop the lock to avoid a deadlock when calling another_function.
// More processing
// ...
// ...
let thread_handle = another_function();
thread_handle.join().unwrap();
}
// From another part of the program and possibly from another thread we
// lock MY_DEFERRED and call regular_funcion on it.
fn another_function() -> JoinHandle<()> {
std::thread::spawn(|| {
let mut lock = MY_DEFERRED.lock().unwrap();
if let Some(deferred) = lock.as_mut() {
deferred.regular_function();
}
})
}
您可以在Rust Playground中执行上述代码并检查它11
是否正确打印。
引入需要静态生命周期的结构函数
现在,假设我在其中添加了一个函数,该函数DeferredStruct
将创建一个工作线程以执行一些需要很长时间的计算:
pub struct DeferredStruct {
internal_field: u32,
}
impl DeferredStruct {
pub fn new(internal_field: u32) -> Self {
Self {
internal_field,
}
}
pub fn regular_function(&mut self) {
self.internal_field += 1;
println!("{}", self.internal_field);
}
pub fn static_function(&'static mut self) {
std::thread::spawn(move || {
// Do something really long.
// Finally I make some changes on self
self.internal_field += 100;
});
}
}
在这种情况下,需要&mut self
有一个'static
生命周期:
error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement.
因此,该函数将采用&'static mut self
.
当试图借用as和的DeferredStruct
内部Option
时,问题就来了。MY_DEFERRED
'static
mut
如果我不能借钱'static
,mut
那么我不能打电话deferred.static_function()
。因为价值不会存在足够长的时间。
error[E0597]: `lock` does not live long enough
--> src/main.rs:57:33
|
57 | if let Some(deferred) = lock.as_mut() {
| ^^^^---------
| |
| borrowed value does not live long enough
| argument requires that `lock` is borrowed for `'static`
...
60 | })
| - `lock` dropped here while still borrowed
这里有一个Rust Playground中的最小可重现示例。
TL;博士
是否可以借用在运行时创建的对象(不一定是在程序的立即启动时创建的)在 aMutex<Option<T>>
中作为可变对象并'static
终身使用?
任何帮助表示赞赏。