repose_core/
scope_cache.rs1use std::cell::RefCell;
2use std::collections::HashMap;
3
4use crate::View;
5
6thread_local! {
7 static CURRENT_SCOPE_KEY: RefCell<Option<String>> =
9 const { RefCell::new(None) };
10
11 static SCOPE_SIGNAL_DEPS: RefCell<HashMap<usize, Vec<String>>> =
15 RefCell::new(HashMap::new());
16}
17
18pub fn record_scope_signal_dep(signal_id: usize) {
21 CURRENT_SCOPE_KEY.with(|key| {
22 if let Some(ref key) = *key.borrow() {
23 SCOPE_SIGNAL_DEPS.with(|deps| {
24 let mut deps = deps.borrow_mut();
25 deps.entry(signal_id).or_default().push(key.clone());
26 });
27 }
28 });
29}
30
31pub fn mark_scope_deps_dirty(signal_id: usize) {
34 SCOPE_SIGNAL_DEPS.with(|deps| {
35 let deps = deps.borrow();
36 if let Some(keys) = deps.get(&signal_id) {
37 for key in keys {
38 crate::runtime::COMPOSER.with(|c| {
39 let mut c = c.borrow_mut();
40 if let Some(cache) = c.scope_caches.get_mut(key) {
41 cache.clean = false;
42 }
43 });
44 }
45 }
46 });
47}
48
49pub fn with_scope_key<R>(key: &str, f: impl FnOnce() -> R) -> R {
51 CURRENT_SCOPE_KEY.with(|k| {
52 let prev = k.borrow_mut().take();
53 *k.borrow_mut() = Some(key.to_string());
54 let result = f();
55 *k.borrow_mut() = prev;
56 result
57 })
58}
59
60pub fn clear_scope_deps(key: &str) {
64 SCOPE_SIGNAL_DEPS.with(|deps| {
65 let mut deps = deps.borrow_mut();
66 deps.retain(|_, keys| {
67 keys.retain(|k| k != key);
68 !keys.is_empty()
69 });
70 });
71}
72
73pub struct ScopeCache {
75 pub input_hash: u64,
77 pub view: View,
79 pub slot_delta: usize,
81 pub clean: bool,
83}
84
85pub fn should_run(key: &str, input_hash: u64) -> bool {
87 crate::runtime::COMPOSER.with(|c| {
88 let c = c.borrow();
89 match c.scope_caches.get(key) {
90 Some(cache) => !cache.clean || cache.input_hash != input_hash,
91 None => true,
92 }
93 })
94}
95
96pub fn get_cached(key: &str, _s: &mut crate::runtime::Scheduler) -> View {
100 crate::runtime::COMPOSER.with(|c| {
101 let mut c = c.borrow_mut();
102 let (slot_delta, view) = {
103 let cache = c
104 .scope_caches
105 .get(key)
106 .expect("scope_cache::get_cached called but no cache entry found");
107 (cache.slot_delta, cache.view.clone())
108 };
109
110 c.cursor += slot_delta;
111 view
112 })
113}
114
115pub fn set_cache(key: &str, input_hash: u64, view: View, slot_delta: usize) {
117 crate::runtime::COMPOSER.with(|c| {
118 let mut c = c.borrow_mut();
119 c.scope_caches.insert(
120 key.to_string(),
121 ScopeCache {
122 input_hash,
123 view,
124 slot_delta,
125 clean: true,
126 },
127 );
128 });
129}