egui/cache/
frame_cache.rs1use super::CacheTrait;
2
3pub trait ComputerMut<Key, Value>: 'static + Send + Sync {
6 fn compute(&mut self, key: Key) -> Value;
7}
8
9pub struct FrameCache<Value, Computer> {
13 generation: u32,
14 computer: Computer,
15 cache: nohash_hasher::IntMap<u64, (u32, Value)>,
16}
17
18impl<Value, Computer> Default for FrameCache<Value, Computer>
19where
20 Computer: Default,
21{
22 fn default() -> Self {
23 Self::new(Computer::default())
24 }
25}
26
27impl<Value, Computer> FrameCache<Value, Computer> {
28 pub fn new(computer: Computer) -> Self {
29 Self {
30 generation: 0,
31 computer,
32 cache: Default::default(),
33 }
34 }
35
36 pub fn evict_cache(&mut self) {
38 let current_generation = self.generation;
39 self.cache.retain(|_key, cached| {
40 cached.0 == current_generation });
42 self.generation = self.generation.wrapping_add(1);
43 }
44}
45
46impl<Value, Computer> FrameCache<Value, Computer> {
47 pub fn get<Key>(&mut self, key: Key) -> &Value
50 where
51 Key: Copy + std::hash::Hash,
52 Computer: ComputerMut<Key, Value>,
53 {
54 let hash = crate::util::hash(key);
55
56 match self.cache.entry(hash) {
57 std::collections::hash_map::Entry::Occupied(entry) => {
58 let cached = entry.into_mut();
59 cached.0 = self.generation;
60 &cached.1
61 }
62 std::collections::hash_map::Entry::Vacant(entry) => {
63 let value = self.computer.compute(key);
64 let inserted = entry.insert((self.generation, value));
65 &inserted.1
66 }
67 }
68 }
69}
70
71impl<Value: 'static + Send + Sync, Computer: 'static + Send + Sync> CacheTrait
72 for FrameCache<Value, Computer>
73{
74 fn update(&mut self) {
75 self.evict_cache();
76 }
77
78 fn len(&self) -> usize {
79 self.cache.len()
80 }
81}