我有一个像这样的昂贵功能:
pub fn get_expensive_value(n: u64): u64 {
let ret = 0;
for 0 .. n {
// expensive stuff
}
ret
}
并且使用相同的参数非常频繁地调用它。它是纯粹的,这意味着它将返回相同的结果并可以使用缓存。
如果这是一个struct方法,我会将一个成员添加到充当缓存的结构中,但它不是。所以我的选择似乎是使用静态:
static mut LAST_VAL: Option<(u64, u64)> = None;
pub fn cached_expensive(n: u64) -> u64 {
unsafe {
LAST_VAL = LAST_VAL.and_then(|(k, v)| {
if k == n {
Some((n,v))
} else {
None
}
}).or_else(|| {
Some((n, get_expensive_value(n)))
});
let (_, v) = LAST_VAL.unwrap();
v
}
}
现在,我必须使用unsafe
。我可以在static mut
中添加RefCell
,而不是const
。但我并不相信这更安全 - 它只是避免使用unsafe
块。我想到了Mutex
,但我认为这不会让我保持线程安全。
重新设计代码以使用结构进行存储实际上不是一种选择。
答案 0 :(得分:3)
我认为最好的选择是使用带互斥锁的全局变量。使用lazy_static可以轻松实现&#34; global&#34;函数内的声明
pub fn cached_expensive(n: u64) -> u64 {
use std::sync::Mutex;
lazy_static! {
static ref LAST_VAL: Mutex<Option<(u64, u64)>> = Mutex::new(None);
}
let mut last = LAST_VAL.lock().unwrap();
let r = last.and_then(|(k, v)| {
if k == n {
Some((n, v))
} else {
None
}
}).or_else(|| Some((n, get_expensive_value(n))));
let (_, v) = r.unwrap();
*last = r;
v
}
答案 1 :(得分:1)
您还可以检出cached项目/板条箱。它通过一个简单的宏来记忆该功能。