por*_*ton 6 mutex lifetime rust automatic-ref-counting
我试图返回一个包含对共享互斥体的引用的结构:
struct Test<'a> {
mutex: Arc<Mutex<()>>,
guard: &'a MutexGuard<'a, ()>,
}
impl<'a> Test<'a> {
pub fn new() -> Self {
let mutex = Arc::new(Mutex::new(()));
let guard = &mutex.lock().unwrap();
Self {
mutex,
guard,
}
}
}
Run Code Online (Sandbox Code Playgroud)
生命周期似乎是正确的:互斥体至少在 的生命周期内存在Test,因此MutexGuard没有对互斥体的停滞引用。但 Rust 给出了错误。如何向 Rust 解释字段的生命周期mutex足够长,可以guard正常工作?
cannot return value referencing local variable `mutex`
returns a value referencing data owned by the current function
Run Code Online (Sandbox Code Playgroud)
顺便说一句,我正在尝试创建一个“mutli-mutex” - 一组键的互斥体(如 中所示HashMap),以阻止下载名称在 hashmap 中的文件(因为它已经在下载)。
这是不可能的,而且你写的很可能不是你想要做的。
互斥锁防护的目标是在互斥锁掉落时将其解锁。如果将守卫的生命周期绑定到互斥体本身,则表示它永远不会被删除,因此互斥体将始终被锁定。
不管怎样,为什么你需要引用守卫本身?通常您不会关心,您只是希望它保持锁定,只要它被引用即可。
也许你想这样做?人们需要更多的背景来看看这是否正是您想要做的:D
use std::sync::{Arc, Mutex, MutexGuard};
struct Test {
mutex: Arc<Mutex<()>>,
}
impl Test {
pub fn new() -> Self {
let mutex = Arc::new(Mutex::new(()));
Self { mutex }
}
pub fn try_download(&self) -> Option<MutexGuard<()>> {
let guard = self.mutex.try_lock();
if guard.is_ok() {
println!("Download started!");
return guard.ok();
} else {
println!("Cannot download since it's already downloading");
return None;
}
}
}
fn main() {
let test = Test::new();
// This could be kept alive like you said in an hashmap, so the guard is not dropped
// v
let a = test.try_download(); // Download started!
let b = test.try_download(); // Cannot download since it's already downloading
}
Run Code Online (Sandbox Code Playgroud)
实际上有2个问题
impl<'a> Test<'a> {
pub fn new() -> Self {
let mutex = Arc::new(Mutex::new(()));
// ^
// This reference has the lifetime of mutex
// v
let guard = &mutex.lock().unwrap();
Self {
mutex, // mutex is moved here, so guard points to something which is at this time
// unknown. This can be known only after the new stack frame is built
guard,
}
}
}
Run Code Online (Sandbox Code Playgroud)
impl<'a> Test<'a> {
pub fn new() -> Self {
let mutex = Arc::new(Mutex::new(()));
// ^
// This reference has the lifetime of mutex
// v
let guard = &mutex.lock().unwrap();
Self {
mutex, // mutex is moved here, so guard points to something which is at this time
// unknown. This can be known only after the new stack frame is built
guard,
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2779 次 |
| 最近记录: |