Arc lifetime does not live long enough from clone()

廉价感情. 提交于 2019-12-24 17:08:09

问题


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:

  1. 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.

  2. Mutex::get_mut method requires &mut self, while it is impossible to get it directly from Arc.

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!