summaryrefslogtreecommitdiff
path: root/src/query.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-05-25 21:31:12 +0200
committerLaurenz <laurmaedje@gmail.com>2022-05-25 21:56:22 +0200
commit0170913d5413aab4c1f2bd7d56b9b7138f676012 (patch)
treefbe77af9ac3c3cfa63ffde3d861987e8d1276ac5 /src/query.rs
parentb6b6e3692404e32873892810bebeb1122f34c52e (diff)
Rebrand queries as memoization
Diffstat (limited to 'src/query.rs')
-rw-r--r--src/query.rs121
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);