Skip to main content

lgui_core/renderer/
cache.rs

1use std::{cell::RefCell, sync::Arc};
2
3#[derive(Clone, Debug, Default, PartialEq, Eq)]
4pub struct StaticLayerMemoryCacheStats {
5    pub entry_count: usize,
6    pub bytes: usize,
7    pub budget_bytes: usize,
8    pub hits: u64,
9    pub misses: u64,
10    pub stores: u64,
11    pub evictions: u64,
12}
13
14#[derive(Clone, Debug, Default, PartialEq, Eq)]
15pub struct StaticLayerMemoryCachePrefixStats {
16    pub entry_count: usize,
17    pub bytes: usize,
18}
19
20#[derive(Clone)]
21pub struct RenderCacheHandle {
22    stats: Arc<dyn Fn() -> StaticLayerMemoryCacheStats + Send + Sync>,
23    prefix_stats: Arc<dyn Fn(&str) -> StaticLayerMemoryCachePrefixStats + Send + Sync>,
24    prefix_entry_ids: Arc<dyn Fn(&str) -> Vec<String> + Send + Sync>,
25}
26
27impl RenderCacheHandle {
28    pub fn new(
29        stats: impl Fn() -> StaticLayerMemoryCacheStats + Send + Sync + 'static,
30        prefix_stats: impl Fn(&str) -> StaticLayerMemoryCachePrefixStats + Send + Sync + 'static,
31        prefix_entry_ids: impl Fn(&str) -> Vec<String> + Send + Sync + 'static,
32    ) -> Self {
33        Self {
34            stats: Arc::new(stats),
35            prefix_stats: Arc::new(prefix_stats),
36            prefix_entry_ids: Arc::new(prefix_entry_ids),
37        }
38    }
39}
40
41thread_local! {
42    static RENDER_CACHE: RefCell<Option<RenderCacheHandle>> = const { RefCell::new(None) };
43}
44
45pub(crate) struct RenderCacheGuard {
46    previous: Option<RenderCacheHandle>,
47}
48
49impl Drop for RenderCacheGuard {
50    fn drop(&mut self) {
51        RENDER_CACHE.with(|current| {
52            *current.borrow_mut() = self.previous.take();
53        });
54    }
55}
56
57pub(crate) fn install_render_cache(handle: RenderCacheHandle) -> RenderCacheGuard {
58    let previous = RENDER_CACHE.with(|current| current.borrow_mut().replace(handle));
59    RenderCacheGuard { previous }
60}
61
62pub fn static_layer_cache_stats() -> StaticLayerMemoryCacheStats {
63    RENDER_CACHE.with(|current| {
64        current
65            .borrow()
66            .as_ref()
67            .map_or_else(StaticLayerMemoryCacheStats::default, |cache| {
68                (cache.stats)()
69            })
70    })
71}
72
73pub fn static_layer_cache_stats_for_prefix(prefix: &str) -> StaticLayerMemoryCachePrefixStats {
74    RENDER_CACHE.with(|current| {
75        current
76            .borrow()
77            .as_ref()
78            .map_or_else(StaticLayerMemoryCachePrefixStats::default, |cache| {
79                (cache.prefix_stats)(prefix)
80            })
81    })
82}
83
84pub fn static_layer_cache_entry_ids_for_prefix(prefix: &str) -> Vec<String> {
85    RENDER_CACHE.with(|current| {
86        current
87            .borrow()
88            .as_ref()
89            .map_or_else(Vec::new, |cache| (cache.prefix_entry_ids)(prefix))
90    })
91}
92
93#[cfg(test)]
94#[path = "cache_test.rs"]
95mod tests;