У меня есть следующий шаблон во многих моих функциях:
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
?
lock()
возвращаетMutexGuard
, а не само значение. Вы можете получить доступ к значению, хранящемуся внутри, потому что оно реализуетDeref
иDerefMut
, но вы все равно ссылаетесь на защиту мьютекса. Когда защита мьютекса выходит за пределы области действия, ваша ссылка будет указывать на освобожденную память, поэтому ржавчина предотвращает это. (Помните, что блокировка мьютекса будет снята, как только защита мьютекса выйдет из области действия!!!) PS: Вместо того, чтобы скрывать.expect()
в другом методе, вы должны правильно обработать случай ошибки. - person Svetlin Zarev   schedule 27.11.2019expect
и обрабатываю ошибку, но обработка ошибок одинакова во всех функциях. Опять же, как мне избежать повторения в этом случае? Единственный способ, который я могу придумать, - это функция более высокого порядка - это идиоматично? - person Vittorio Romeo   schedule 27.11.2019&mut State
наMutexGuard<State>
. @Svetlin: Я думаю, это то, что вы хотели выразить, верно? - person CoronA   schedule 27.11.2019MutexGuard
. Если OP возвращает MutexGuard ->, то это должно работать. - person Svetlin Zarev   schedule 27.11.2019MutexGuard
, не стесняйтесь добавлять это в качестве ответа. - person Vittorio Romeo   schedule 27.11.2019