我的许多功能中都有以下模式:
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") }编译失败:
错误:无法返回引用临时值的值
ERROR: cannot return value referencing temporary value
这让我相信 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.
更多推荐
可变借用互斥体内部的对象
发布评论