As per thread I've had the need to create a global non-mutable singleton to store some static data.
#[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);
}
It's single threaded so I'm not using Arc/Mutex.
How can I get RefData::singleton() to last long enough to return a reference to the value thats in the btreemap
And that is, actually, the first issue.
Arc
andMutex
provide more than just thread-safety, they also provide shallow copies, so that allSingletonReader
share the same storage underneath, and therefore the lifetime of the storage is not linked to that of theSingletonReader
.Thus, you should rather return a
&'static
reference toRefData
.And now, this implementation will work:
However, it is slightly skewed: lifetime inference makes it so that it is interpreted as:
Which is perhaps not what you wish for, as the lifetime of the
String
really is'static
here, and therefore you should rather aim for: