从全局结构中获取数据会产生错误"借来的值不够长并且#34;

时间:2015-06-25 13:36:55

标签: rust lifetime

根据thread,我需要创建一个全局不可变的单例来存储一些静态数据。

#[derive(Clone)]
struct RefData {
    atm_vol : BTreeMap<String,String>,
    delta_vol : BTreeMap<String,String>
}

impl RefData {
    fn singleton() -> RefData {
        static mut g_RefData : *const RefData = 0 as *const RefData;
        static G_ONCE : Once = ONCE_INIT;
        unsafe {
            G_ONCE.call_once(|| {
                let mut ref_data = RefData { atm_vol : (BTreeMap::new()),
                                             delta_vol : (BTreeMap::new()) };
                ref_data.init();
                g_RefData = mem::transmute(Box::new(ref_data));
                });

            (*g_RefData).clone()
       }
    }

    fn init(&mut self) {
        self.atm_vol.insert("xcu".to_string(),"XCU_USD_VOL_DT".to_string());
        self.delta_vol.insert("xcu".to_string(),"XCU_USD_VOL_SKEW_M".to_string());
    }
    // This doesn't work as singleton doesn't last long enough
    fn vol_handle(asset : &str) -> Option<&String> {
        RefData::singleton().atm_vol.get(asset)
    }
}


#[test]
fn test_refdata() {
    let t = RefData::vol_handle("xcu");
    println!("{:?}",t);

}

它是单线程的,因此我没有使用Arc / Mutex。

如何让RefData :: singleton()持续足够长的时间以返回对btreemap中值的引用

1 个答案:

答案 0 :(得分:2)

  

它是单线程的,所以我没有使用Arc / Mutex。

实际上,这是第一个问题。

ArcMutex提供更多而不仅仅是线程安全,它们还提供浅层副本,以便所有SingletonReader共享下面的相同存储,因此存储的生命周期与SingletonReader的生命周期没有关联。

因此,您应该返回&'static RefData的引用。

fn singleton() -> &'static RefData {
    static mut g_RefData : *const RefData = 0 as *const RefData;
    static G_ONCE : Once = ONCE_INIT;
    unsafe {
        G_ONCE.call_once(|| {
            let mut ref_data = RefData { atm_vol : (BTreeMap::new()),
                                         delta_vol : (BTreeMap::new()) };
            ref_data.init();
            g_RefData = mem::transmute(Box::new(ref_data));
            });

        &*g_RefData
   }
}

现在,这个实现将起作用:

fn vol_handle(asset : &str) -> Option<&String> {
    RefData::singleton().atm_vol.get(asset)
}

然而,它有点倾斜:终身推理使它被解释为:

fn vol_handle<'a>(asset : &'a str) -> Option<&'a String> {
    RefData::singleton().atm_vol.get(asset)
}

这可能不是你想要的,因为String的生命周期真的是'static,因此你应该瞄准:

fn vol_handle(asset : &str) -> Option<&'static String> {
    RefData::singleton().atm_vol.get(asset)
}