1pub trait ComputerMut<Key, Value>: 'static + Send + Sync {
11 fn compute(&mut self, key: Key) -> Value;
12}
13
14pub struct FrameCache<Value, Computer> {
18 generation: u32,
19 computer: Computer,
20 cache: nohash_hasher::IntMap<u64, (u32, Value)>,
21}
22
23impl<Value, Computer> Default for FrameCache<Value, Computer>
24where
25 Computer: Default,
26{
27 fn default() -> Self {
28 Self::new(Computer::default())
29 }
30}
31
32impl<Value, Computer> FrameCache<Value, Computer> {
33 pub fn new(computer: Computer) -> Self {
34 Self {
35 generation: 0,
36 computer,
37 cache: Default::default(),
38 }
39 }
40
41 pub fn evice_cache(&mut self) {
43 let current_generation = self.generation;
44 self.cache.retain(|_key, cached| {
45 cached.0 == current_generation });
47 self.generation = self.generation.wrapping_add(1);
48 }
49}
50
51impl<Value, Computer> FrameCache<Value, Computer> {
52 pub fn get<Key>(&mut self, key: Key) -> Value
55 where
56 Key: Copy + std::hash::Hash,
57 Value: Clone,
58 Computer: ComputerMut<Key, Value>,
59 {
60 let hash = crate::util::hash(key);
61
62 match self.cache.entry(hash) {
63 std::collections::hash_map::Entry::Occupied(entry) => {
64 let cached = entry.into_mut();
65 cached.0 = self.generation;
66 cached.1.clone()
67 }
68 std::collections::hash_map::Entry::Vacant(entry) => {
69 let value = self.computer.compute(key);
70 entry.insert((self.generation, value.clone()));
71 value
72 }
73 }
74 }
75}
76
77#[allow(clippy::len_without_is_empty)]
78pub trait CacheTrait: 'static + Send + Sync {
79 fn update(&mut self);
81
82 fn len(&self) -> usize;
84
85 fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
86}
87
88impl<Value: 'static + Send + Sync, Computer: 'static + Send + Sync> CacheTrait
89 for FrameCache<Value, Computer>
90{
91 fn update(&mut self) {
92 self.evice_cache();
93 }
94
95 fn len(&self) -> usize {
96 self.cache.len()
97 }
98
99 fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
100 self
101 }
102}
103
104#[derive(Default)]
121pub struct CacheStorage {
122 caches: ahash::HashMap<std::any::TypeId, Box<dyn CacheTrait>>,
123}
124
125impl CacheStorage {
126 pub fn cache<FrameCache: CacheTrait + Default>(&mut self) -> &mut FrameCache {
127 self.caches
128 .entry(std::any::TypeId::of::<FrameCache>())
129 .or_insert_with(|| Box::<FrameCache>::default())
130 .as_any_mut()
131 .downcast_mut::<FrameCache>()
132 .unwrap()
133 }
134
135 fn num_values(&self) -> usize {
137 self.caches.values().map(|cache| cache.len()).sum()
138 }
139
140 pub fn update(&mut self) {
142 for cache in self.caches.values_mut() {
143 cache.update();
144 }
145 }
146}
147
148impl Clone for CacheStorage {
149 fn clone(&self) -> Self {
150 Self::default()
152 }
153}
154
155impl std::fmt::Debug for CacheStorage {
156 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
157 write!(
158 f,
159 "FrameCacheStorage[{} caches with {} elements]",
160 self.caches.len(),
161 self.num_values()
162 )
163 }
164}