1use super::CacheTrait;
23/// Something that does an expensive computation that we want to cache
4/// to save us from recomputing it each frame.
5pub trait ComputerMut<Key, Value>: 'static + Send + Sync {
6fn compute(&mut self, key: Key) -> Value;
7}
89/// Caches the results of a computation for one frame.
10/// If it is still used next frame, it is not recomputed.
11/// If it is not used next frame, it is evicted from the cache to save memory.
12pub struct FrameCache<Value, Computer> {
13 generation: u32,
14 computer: Computer,
15 cache: nohash_hasher::IntMap<u64, (u32, Value)>,
16}
1718impl<Value, Computer> Default for FrameCache<Value, Computer>
19where
20Computer: Default,
21{
22fn default() -> Self {
23Self::new(Computer::default())
24 }
25}
2627impl<Value, Computer> FrameCache<Value, Computer> {
28pub fn new(computer: Computer) -> Self {
29Self {
30 generation: 0,
31 computer,
32 cache: Default::default(),
33 }
34 }
3536/// Must be called once per frame to clear the cache.
37pub fn evict_cache(&mut self) {
38let current_generation = self.generation;
39self.cache.retain(|_key, cached| {
40 cached.0 == current_generation // only keep those that were used this frame
41});
42self.generation = self.generation.wrapping_add(1);
43 }
44}
4546impl<Value, Computer> FrameCache<Value, Computer> {
47/// Get from cache (if the same key was used last frame)
48 /// or recompute and store in the cache.
49pub fn get<Key>(&mut self, key: Key) -> Value
50where
51Key: Copy + std::hash::Hash,
52 Value: Clone,
53 Computer: ComputerMut<Key, Value>,
54 {
55let hash = crate::util::hash(key);
5657match self.cache.entry(hash) {
58 std::collections::hash_map::Entry::Occupied(entry) => {
59let cached = entry.into_mut();
60 cached.0 = self.generation;
61 cached.1.clone()
62 }
63 std::collections::hash_map::Entry::Vacant(entry) => {
64let value = self.computer.compute(key);
65 entry.insert((self.generation, value.clone()));
66 value
67 }
68 }
69 }
70}
7172impl<Value: 'static + Send + Sync, Computer: 'static + Send + Sync> CacheTrait
73for FrameCache<Value, Computer>
74{
75fn update(&mut self) {
76self.evict_cache();
77 }
7879fn len(&self) -> usize {
80self.cache.len()
81 }
8283fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
84self
85}
86}