问题
I'm trying to create a parameter structure that will possibly be shared between threads. It has a member called layer_storage
which some members will need to mutate. I tried the following code, but am getting an error saying that the cloned Arc
does not live long enough. This same member worked fine before the addition of Arc<Mutex<>>
.
use std::sync::{Arc, Mutex};
#[derive(Clone)]
pub struct Params {
pub optional: Vec<f32>,
}
pub struct ParamManager {
layer_storage: Arc<Mutex<Vec<Params>>>,
}
impl Default for ParamManager {
fn default() -> ParamManager {
ParamManager {
layer_storage: Arc::new(Mutex::new(vec![Params { optional: vec![1.0f32, 2.0f32] },
Params { optional: vec![3.0f32, 4.0f32] }])),
}
}
}
impl ParamManager {
pub fn get_mut_params(&mut self, layer_index: usize) -> &mut Params {
let layers_arc = self.layer_storage.clone();
let layers = layers_arc.get_mut().unwrap();
// tried this initially:
// let layers = self.layer_storage.clone().get_mut().unwrap();
assert!(layers.len() - 1 >= layer_index);
&mut layers[layer_index]
}
}
fn main() {
let mut bla = ParamManager::default();
let i = bla.get_mut_params(0);
}
(Playground)
回答1:
As @Shepmaster says you can't just return a reference to something inside the Arc<Mutex<T>>
from the get_mut_params
; this is one of the guarantees you get from them!
One solution which works in may cases is to turn the function inside out; rather than returning a mutable reference, take a closure which is given the mutable reference:
impl ParamManager {
pub fn with_mut_params<F>(&mut self, layer_index: usize, mut f: F)
where F: FnMut(&mut Params) {
let layers_arc = self.layer_storage.clone();
let layers = layers_arc.lock().unwrap();
f(&mut layers[layer_index]);
}
}
fn main() {
let mut bla = ParamManager::default();
// Context used by the closure
let some_var: i32 = 7;
let other_var: mut MyContext = do_something();
bla.with_mut_params(0, |i| {
// do stuff with i
...
// A closure has access to surrounding variables
other_var.foo(i, some_var);
});
}
回答2:
I think the compiler is right in your case.
There are two obvious errors here:
The
layers_arc
value lives just until the block end, and then it's destructor will decrement the reference counter and maybe drop the whole value. Or it could be dropped in other thread in any time. So it is illegal to return a pointer to it's contents.Mutex::get_mut
method requires&mut self
, while it is impossible to get it directly fromArc
.
So you have to refactor your code somehow. For example, you could guard each separate item in vector with Arc<Mutex>
and return them by value using .clone()
.
来源:https://stackoverflow.com/questions/37379952/arc-lifetime-does-not-live-long-enough-from-clone