Rust 返回对惰性静态rBlock中T的引用<;选项<;T>>;?
我有一个懒惰的静态结构,我希望能够在程序开始执行时将其设置为一些随机值,然后在以后得到。这段愚蠢的小片段可以作为一个例子:Rust 返回对惰性静态rBlock中T的引用<;选项<;T>>;?,rust,readwritelock,lazy-static,Rust,Readwritelock,Lazy Static,我有一个懒惰的静态结构,我希望能够在程序开始执行时将其设置为一些随机值,然后在以后得到。这段愚蠢的小片段可以作为一个例子: use lazy_static::lazy_static; use std::sync::RwLock; struct Answer(i8); lazy_static! { static ref ANSWER: RwLock<Option<Answer>> = RwLock::new(None); } fn answer_questio
use lazy_static::lazy_static;
use std::sync::RwLock;
struct Answer(i8);
lazy_static! {
static ref ANSWER: RwLock<Option<Answer>> = RwLock::new(None);
}
fn answer_question() {
*ANSWER.write().unwrap() = Some(Answer(42));
}
fn what_is_the_answer() -> &'static Answer {
ANSWER
.read()
.unwrap()
.as_ref()
.unwrap()
}
我知道您不能返回对临时值的引用。但是我想返回一个对ANSWER
的引用,它是静态的,与临时相反!我猜第一次调用unwrap
返回的问题是RwLockReadGuard
我可以通过更改返回类型来获得要编译的代码:
fn what_is_the_answer() -> RwLockReadGuard<'static, Option<Answer>> {
ANSWER
.read()
.unwrap()
}
我是否可以通过此函数返回对静态
答案的引用?我可以通过某种映射让它返回rBlockReadGuard
吗?据我所知,在lazy\u static
中初始化Answer
时,无法计算Answer
的值,但这取决于只有在调用Answer\u question
时才知道的参数。以下可能不是最优雅的解决方案,但它允许对仅依赖于运行时已知参数的值进行&'static
-引用
基本方法是使用两个
lazy\u static-值,其中一个作为“代理”执行必要的同步,另一个作为值本身。这避免了在访问应答时必须访问多层锁和展开选项
-值
通过等待CondVar
,将初始化应答
-值,该值在计算完该值后将发出信号。然后将该值放入lazy_static
中,从那时起不可移动。因此,和“静态”
是可能的(请参见获取答案()。我选择了String
作为示例类型。请注意,访问ANSWER
而不调用generate\u the\u ANSWER()
将导致初始化永久等待,从而使程序死锁
use std::{sync, thread};
lazy_static::lazy_static! {
// A proxy to synchronize when the value is generated
static ref ANSWER_PROXY: (sync::Mutex<Option<String>>, sync::Condvar) = {
(sync::Mutex::new(None), sync::Condvar::new())
};
// The actual value, which is initialized from the proxy and stays in place
// forever, hence allowing &'static access
static ref ANSWER: String = {
let (lock, cvar) = &*ANSWER_PROXY;
let mut answer = lock.lock().unwrap();
loop {
// As long as the proxy is None, the answer has not been generated
match answer.take() {
None => answer = cvar.wait(answer).unwrap(),
Some(answer) => return answer,
}
}
};
}
// Generate the answer and place it in the proxy. The `param` is just here
// to demonstrate we can move owned values into the proxy
fn generate_the_answer(param: String) {
// We don't need a thread here, yet we can
thread::spawn(move || {
println!("Generating the answer...");
let mut s = String::from("Hello, ");
s.push_str(¶m);
thread::sleep(std::time::Duration::from_secs(1));
let (lock, cvar) = &*ANSWER_PROXY;
*lock.lock().unwrap() = Some(s);
cvar.notify_one();
println!("Answer generated.");
});
}
// Nothing to see here, except that we have a &'static reference to the answer
fn get_the_answer() -> &'static str {
println!("Asking for the answer...");
&ANSWER
}
fn main() {
println!("Hello, world!");
// Accessing `ANSWER` without generating it will deadlock!
//get_the_answer();
generate_the_answer(String::from("John!"));
println!("The answer is \"{}\"", get_the_answer());
// The second time a value is generated, noone is listening.
// This is the flipside of `ANSWER` being a &'static
generate_the_answer(String::from("Peter!"));
println!("The answer is still \"{}\"", get_the_answer());
}
使用std:{sync,thread};
懒惰的静态::懒惰的静态!{
//生成值时要同步的代理
静态引用应答\u代理:(sync::Mutex,sync::Condvar)={
(sync::Mutex::new(无),sync::Condvar::new()
};
//实际值,从代理初始化并保持不变
//永远,因此允许&“静态访问”
静态参考答案:字符串={
let(lock,cvar)=&*回答_PROXY;
让mut-answer=lock.lock().unwrap();
环路{
//只要代理为None,就不会生成答案
匹配答案{
None=>answer=cvar.wait(answer).unwrap(),
Some(答案)=>返回答案,
}
}
};
}
//生成答案并将其放置在代理中。“param”就在这里
//为了演示,我们可以将所拥有的值移动到代理中
fn生成答案(参数:字符串){
//我们这里不需要线,但我们可以
线程::生成(移动| |{
println!(“生成答案…”);
让mut s=String::from(“Hello,”);
s、 推送参数(¶m);
线程::睡眠(std::time::Duration::from_secs(1));
let(lock,cvar)=&*回答_PROXY;
*lock.lock().unwrap()=一些;
cvar.notify_one();
println!(“生成答案”);
});
}
//这里没有什么可看的,除了我们对答案有一个&“静态引用”
fn获取答案()->&'{
println!(“询问答案…”);
&答复
}
fn main(){
println!(“你好,世界!”);
//访问'ANSWER'而不生成它将导致死锁!
//获得答案();
生成答案(字符串::from(“John!”);
println!(“答案是\“{}\”,获取答案();
//第二次生成值时,无人监听。
//这是'ANSWER'作为&'static的另一面
生成答案(字符串::from(“Peter!”);
println!(“答案仍然是\“{}\”,获取答案();
}
就是为此而设计的:使用中的.set(…).unwrap()
和中的和中的.get().unwrap()
中的答案是什么
正如您所猜测的那样,该示例将不起作用,因为返回的引用(从选项)绑定到锁止
,锁止
。借用检查器正在阻止对ANSWER
的引用从锁中逃逸。你到底想在这里实现什么?@user2722968我想在程序启动时设置一个全局变量(基于配置文件中的一些设置),并且我希望以后能够从程序中的不同位置以符合人体工程学的方式访问它。所有事情都发生在同一个线程中。@user2722968我编辑以添加更多信息。
what_is_the_answer().as_ref().unwrap()
use std::{sync, thread};
lazy_static::lazy_static! {
// A proxy to synchronize when the value is generated
static ref ANSWER_PROXY: (sync::Mutex<Option<String>>, sync::Condvar) = {
(sync::Mutex::new(None), sync::Condvar::new())
};
// The actual value, which is initialized from the proxy and stays in place
// forever, hence allowing &'static access
static ref ANSWER: String = {
let (lock, cvar) = &*ANSWER_PROXY;
let mut answer = lock.lock().unwrap();
loop {
// As long as the proxy is None, the answer has not been generated
match answer.take() {
None => answer = cvar.wait(answer).unwrap(),
Some(answer) => return answer,
}
}
};
}
// Generate the answer and place it in the proxy. The `param` is just here
// to demonstrate we can move owned values into the proxy
fn generate_the_answer(param: String) {
// We don't need a thread here, yet we can
thread::spawn(move || {
println!("Generating the answer...");
let mut s = String::from("Hello, ");
s.push_str(¶m);
thread::sleep(std::time::Duration::from_secs(1));
let (lock, cvar) = &*ANSWER_PROXY;
*lock.lock().unwrap() = Some(s);
cvar.notify_one();
println!("Answer generated.");
});
}
// Nothing to see here, except that we have a &'static reference to the answer
fn get_the_answer() -> &'static str {
println!("Asking for the answer...");
&ANSWER
}
fn main() {
println!("Hello, world!");
// Accessing `ANSWER` without generating it will deadlock!
//get_the_answer();
generate_the_answer(String::from("John!"));
println!("The answer is \"{}\"", get_the_answer());
// The second time a value is generated, noone is listening.
// This is the flipside of `ANSWER` being a &'static
generate_the_answer(String::from("Peter!"));
println!("The answer is still \"{}\"", get_the_answer());
}