问题描述
我的许多功能中都有以下模式:
I have the following pattern in many of my functions:
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")
一遍遍重复,所以想重构为一个函数,为了写类似的东西
&mut *data.lock().expect("Could not lock mutex")
is repeated over and over, so I would like to refactor it to a function, in order to write something like
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
调用在这个游乐场.
This makes me believe that data.state.lock().expect("...")
returns by value. However, I can see the state being mutated through multiple foo
calls on this playground.
这里发生了什么?为什么我这个看似简单的重构编译失败?
我希望以下内容也能正常工作:
I would expect the following to work as well:
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
参数之一不匹配?
Why doesn't the lifetime of whatever is returned from lock
match the one of the data
parameter?
推荐答案
lock()
方法返回 MutexGuard
而不是对受保护对象的直接引用.您可以使用对象引用,因为 MutexGuard
实现了 Deref
和 DerefMut
,但是您仍然需要 mutex-guard 在范围内,因为当它超出范围时,互斥锁将被释放.此外,对内部对象的引用的生命周期与互斥保护的生命周期绑定,因此编译器将不允许您在没有互斥保护的情况下使用对内部对象的引用.
The lock()
method returns MutexGuard
instead of a direct reference to the guarded object. You are able to work with object reference, because MutexGuard
implements Deref
and DerefMut
, but you still need the mutex-guard to be in scope, because when it goes out of scope the mutex lock will be released. Also the lifetime of the reference to the iner object is bound to the lifetime of the mutex guard, so the compiler will not allow you to use the reference to the inner object without the mutex guard.
您可以在宏或方法中提取常用逻辑,但它应返回 MutexGuard 而不是对内部对象的引用.
You can extract your common logic in a macro or a method, but it should return MutexGuard instead of a reference to the inner object.
这篇关于可变借用互斥体内部的对象 - 如何重构?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!