use std::cell::RefCell;
use std::collections::HashMap;
use crate::View;
thread_local! {
static CURRENT_SCOPE_KEY: RefCell<Option<String>> =
const { RefCell::new(None) };
static SCOPE_SIGNAL_DEPS: RefCell<HashMap<usize, Vec<String>>> =
RefCell::new(HashMap::new());
}
pub fn record_scope_signal_dep(signal_id: usize) {
CURRENT_SCOPE_KEY.with(|key| {
if let Some(ref key) = *key.borrow() {
SCOPE_SIGNAL_DEPS.with(|deps| {
let mut deps = deps.borrow_mut();
deps.entry(signal_id).or_default().push(key.clone());
});
}
});
}
pub fn mark_scope_deps_dirty(signal_id: usize) {
SCOPE_SIGNAL_DEPS.with(|deps| {
let deps = deps.borrow();
if let Some(keys) = deps.get(&signal_id) {
for key in keys {
crate::runtime::COMPOSER.with(|c| {
let mut c = c.borrow_mut();
if let Some(cache) = c.scope_caches.get_mut(key) {
cache.clean = false;
}
});
}
}
});
}
pub fn with_scope_key<R>(key: &str, f: impl FnOnce() -> R) -> R {
CURRENT_SCOPE_KEY.with(|k| {
let prev = k.borrow_mut().take();
*k.borrow_mut() = Some(key.to_string());
let result = f();
*k.borrow_mut() = prev;
result
})
}
pub fn clear_scope_deps(key: &str) {
SCOPE_SIGNAL_DEPS.with(|deps| {
let mut deps = deps.borrow_mut();
deps.retain(|_, keys| {
keys.retain(|k| k != key);
!keys.is_empty()
});
});
}
pub struct ScopeCache {
pub input_hash: u64,
pub view: View,
pub slot_delta: usize,
pub clean: bool,
}
pub fn should_run(key: &str, input_hash: u64) -> bool {
crate::runtime::COMPOSER.with(|c| {
let c = c.borrow();
match c.scope_caches.get(key) {
Some(cache) => !cache.clean || cache.input_hash != input_hash,
None => true,
}
})
}
pub fn get_cached(key: &str, _s: &mut crate::runtime::Scheduler) -> View {
crate::runtime::COMPOSER.with(|c| {
let mut c = c.borrow_mut();
let (slot_delta, view) = {
let cache = c
.scope_caches
.get(key)
.expect("scope_cache::get_cached called but no cache entry found");
(cache.slot_delta, cache.view.clone())
};
c.cursor += slot_delta;
view
})
}
pub fn set_cache(key: &str, input_hash: u64, view: View, slot_delta: usize) {
crate::runtime::COMPOSER.with(|c| {
let mut c = c.borrow_mut();
c.scope_caches.insert(
key.to_string(),
ScopeCache {
input_hash,
view,
slot_delta,
clean: true,
},
);
});
}