我有一个昂贵的函数,像这样:
pub fn get_expensive_value(n: u64): u64 {
let ret = 0;
for 0 .. n {
// expensive stuff
}
ret
}
这个函数会频繁地使用相同的参数进行调用。它是纯函数,这意味着它将返回相同的结果并且可以使用缓存。
如果这是一个结构体方法,我会添加一个充当缓存的成员到结构体中,但它不是。所以我的选择似乎是使用静态变量:
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
。我可以在const
中放置一个RefCell
,而不是static mut
。但我并不认为这样更安全-它只是避免了使用unsafe
块。我考虑过使用Mutex
,但我认为这也无法保证线程安全。重新设计代码以使用结构体进行存储不是一个真正的选择。
RefCell
或Mutex
可以使其更好,或者提供完全不同的结构替代方案。 - Peter Hallself
),要么它必须存储在全局存储中。后者有一个限制,就是你需要处理对缓存的并发访问。 - ShepmasterArc<Mutex<..>>
的构造看起来就是我需要的。但我会重新考虑是否可以用不同的方式实现。由于我正在处理一个现有的代码库,所以情况并不那么简单。 - Peter Hall