diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-05-25 21:31:12 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-05-25 21:56:22 +0200 |
| commit | 0170913d5413aab4c1f2bd7d56b9b7138f676012 (patch) | |
| tree | fbe77af9ac3c3cfa63ffde3d861987e8d1276ac5 /src/query.rs | |
| parent | b6b6e3692404e32873892810bebeb1122f34c52e (diff) | |
Rebrand queries as memoization
Diffstat (limited to 'src/query.rs')
| -rw-r--r-- | src/query.rs | 121 |
1 files changed, 0 insertions, 121 deletions
diff --git a/src/query.rs b/src/query.rs deleted file mode 100644 index 97af0139..00000000 --- a/src/query.rs +++ /dev/null @@ -1,121 +0,0 @@ -//! Query caching. - -use std::any::Any; -use std::cell::RefCell; -use std::collections::HashMap; -use std::fmt::{self, Display, Formatter}; -use std::hash::Hash; - -thread_local! { - /// The thread-local query cache. - static CACHE: RefCell<Cache> = RefCell::default(); -} - -/// A map from hashes to cache entries. -type Cache = HashMap<u64, CacheEntry>; - -/// Access the cache. -fn with<F, R>(f: F) -> R -where - F: FnOnce(&mut Cache) -> R, -{ - CACHE.with(|cell| f(&mut cell.borrow_mut())) -} - -/// An entry in the query cache. -struct CacheEntry { - /// The query's results. - data: Box<dyn Any>, - /// How many evictions have passed since the entry has been last used. - age: usize, -} - -/// Execute a query. -/// -/// This hashes all inputs to the query and then either returns a cached version -/// from the thread-local query cache or executes the query and saves a copy of -/// the results in the cache. -/// -/// Note that `f` must be a pure function. -pub fn query<I, O>(input: I, f: fn(input: I) -> O) -> O -where - I: Hash, - O: Clone + 'static, -{ - query_ref(input, f, Clone::clone) -} - -/// Execute a query and then call a function with a reference to the result. -/// -/// This hashes all inputs to the query and then either call `g` with a cached -/// version from the thread-local query cache or executes the query, calls `g` -/// with the fresh version and saves the result in the cache. -/// -/// Note that `f` must be a pure function, while `g` does not need to be pure. -pub fn query_ref<I, O, G, R>(input: I, f: fn(input: I) -> O, g: G) -> R -where - I: Hash, - O: 'static, - G: Fn(&O) -> R, -{ - let hash = fxhash::hash64(&input); - let result = with(|cache| { - let entry = cache.get_mut(&hash)?; - entry.age = 0; - entry.data.downcast_ref().map(|output| g(output)) - }); - - result.unwrap_or_else(|| { - let output = f(input); - let result = g(&output); - let entry = CacheEntry { data: Box::new(output), age: 0 }; - with(|cache| cache.insert(hash, entry)); - result - }) -} - -/// Garbage-collect the thread-local query cache. -/// -/// This deletes elements which haven't been used in a while and returns details -/// about the eviction. -pub fn evict() -> Eviction { - with(|cache| { - const MAX_AGE: usize = 5; - - let before = cache.len(); - cache.retain(|_, entry| { - entry.age += 1; - entry.age <= MAX_AGE - }); - - Eviction { before, after: cache.len() } - }) -} - -/// Details about a cache eviction. -pub struct Eviction { - /// The number of items in the cache before the eviction. - pub before: usize, - /// The number of items in the cache after the eviction. - pub after: usize, -} - -impl Display for Eviction { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - writeln!(f, "Before: {}", self.before)?; - writeln!(f, "Evicted: {}", self.before - self.after)?; - writeln!(f, "After: {}", self.after) - } -} - -// These impls are temporary and incorrect. -macro_rules! skip { - ($ty:ty) => { - impl Hash for $ty { - fn hash<H: std::hash::Hasher>(&self, _: &mut H) {} - } - }; -} - -skip!(crate::font::FontStore); -skip!(crate::Context); |
