互斥对象内部互斥对象-如何重构?

罗密欧

我的许多功能中都有以下模式:

use std::sync::{Arc, Mutex};

struct State { 
    value: i32
}

fn foo(data: Arc<Mutex<State>>) {
    let state = &mut data.lock().expect("Could not lock mutex");
    // mutate `state`
}

&mut *data.lock().expect("Could not lock mutex") 重复一遍又一遍,所以我想将其重构为一个函数,以便编写类似

let state = get_state(data); 

我尝试了以下方法:

fn get_state(data: &Arc<Mutex<State>>) -> &mut State {
    &mut data.lock().expect("Could not lock mutex")
}

不能编译为:

错误:无法返回引用临时值的值

这使我相信data.state.lock().expect("...")价值回报。但是,我可以看到在该游乐场通过多次foo调用使状态发生了变化

这里发生了什么?为什么我看似简单的重构无法编译?


编辑:

我希望以下内容也能起作用:

fn get_state<'a>(data: &'a Arc<Mutex<State>>) -> &'a mut State {
    let state: &'a mut State = &mut data.lock().expect("Could not lock mutex");
    state
}

但是它失败了:

   |
12 | fn get_state<'a>(data: &'a Arc<Mutex<State>>) -> &'a mut State {
   |              -- lifetime `'a` defined here
13 |     let state: &'a mut State = &mut data.lock().expect("Could not lock mutex");
   |                -------------        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
   |                |
   |                type annotation requires that borrow lasts for `'a`
14 |     state
15 | }
   | - temporary value is freed at the end of this statement

为什么返回的任何内容的生存期都不lock匹配data参数之一?

斯韦特林·扎列夫(Svetlin Zarev)

lock()方法返回MutexGuard而不是直接引用受保护对象。您可以使用对象引用,因为MutexGuard实现是DerefDerefMut,但是您仍然需要互斥锁保护在范围内,因为当超出范围时,互斥锁将被释放。同样,对内部对象的引用的生存期也与互斥保护的生存期绑定在一起,因此编译器将不允许您在没有互斥保护的情况下使用对内部对象的引用。

您可以在宏或方法中提取常用逻辑,但应返回MutexGuard而不是对内部对象的引用。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章