moonpool_explorer/
context.rs1use std::cell::{Cell, RefCell};
8
9use crate::energy::EnergyBudget;
10use crate::shared_stats::{SharedRecipe, SharedStats};
11use crate::split_loop::{AdaptiveConfig, Parallelism};
12
13thread_local! {
14 static EXPLORER_CTX: RefCell<ExplorerCtx> = RefCell::new(ExplorerCtx::inactive());
16
17 static RNG_GET_COUNT: Cell<fn() -> u64> = const { Cell::new(|| 0) };
19
20 static RNG_RESEED: Cell<fn(u64)> = const { Cell::new(|_| {}) };
22
23 pub(crate) static SHARED_STATS: Cell<*mut SharedStats> = const { Cell::new(std::ptr::null_mut()) };
27
28 pub(crate) static SHARED_RECIPE: Cell<*mut SharedRecipe> = const { Cell::new(std::ptr::null_mut()) };
30
31 pub(crate) static EXPLORED_MAP_PTR: Cell<*mut u8> = const { Cell::new(std::ptr::null_mut()) };
33
34 pub(crate) static COVERAGE_BITMAP_PTR: Cell<*mut u8> = const { Cell::new(std::ptr::null_mut()) };
36
37 pub(crate) static ASSERTION_TABLE: Cell<*mut u8> = const { Cell::new(std::ptr::null_mut()) };
39
40 pub(crate) static ENERGY_BUDGET_PTR: Cell<*mut EnergyBudget> = const { Cell::new(std::ptr::null_mut()) };
42
43 pub(crate) static EACH_BUCKET_PTR: Cell<*mut u8> = const { Cell::new(std::ptr::null_mut()) };
45
46 pub(crate) static BITMAP_POOL: Cell<*mut u8> = const { Cell::new(std::ptr::null_mut()) };
48
49 pub(crate) static BITMAP_POOL_SLOTS: Cell<usize> = const { Cell::new(0) };
51}
52
53pub struct ExplorerCtx {
55 pub active: bool,
57 pub is_child: bool,
59 pub depth: u32,
61 pub max_depth: u32,
63 pub current_seed: u64,
65 pub recipe: Vec<(u64, u64)>,
68 pub timelines_per_split: u32,
70 pub adaptive: Option<AdaptiveConfig>,
72 pub parallelism: Option<Parallelism>,
74 pub warm_start: bool,
76}
77
78impl ExplorerCtx {
79 pub fn inactive() -> Self {
81 Self {
82 active: false,
83 is_child: false,
84 depth: 0,
85 max_depth: 0,
86 current_seed: 0,
87 recipe: Vec::new(),
88 timelines_per_split: 0,
89 adaptive: None,
90 parallelism: None,
91 warm_start: false,
92 }
93 }
94}
95
96pub fn set_rng_hooks(get_count: fn() -> u64, reseed: fn(u64)) {
103 RNG_GET_COUNT.with(|c| c.set(get_count));
104 RNG_RESEED.with(|c| c.set(reseed));
105}
106
107pub(crate) fn rng_get_count() -> u64 {
109 RNG_GET_COUNT.with(|c| (c.get())())
110}
111
112pub(crate) fn rng_reseed(seed: u64) {
114 RNG_RESEED.with(|c| (c.get())(seed));
115}
116
117pub(crate) fn with_ctx<R>(f: impl FnOnce(&ExplorerCtx) -> R) -> R {
119 EXPLORER_CTX.with(|ctx| f(&ctx.borrow()))
120}
121
122pub(crate) fn with_ctx_mut<R>(f: impl FnOnce(&mut ExplorerCtx) -> R) -> R {
124 EXPLORER_CTX.with(|ctx| f(&mut ctx.borrow_mut()))
125}
126
127pub fn explorer_is_active() -> bool {
129 with_ctx(|ctx| ctx.active)
130}
131
132pub fn explorer_is_child() -> bool {
134 with_ctx(|ctx| ctx.is_child)
135}
136
137pub fn get_assertion_table_ptr() -> *mut u8 {
141 ASSERTION_TABLE.with(|c| c.get())
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147
148 #[test]
149 fn test_default_hooks() {
150 assert_eq!(rng_get_count(), 0);
152 rng_reseed(42);
154 }
155
156 #[test]
157 fn test_set_hooks() {
158 thread_local! {
159 static CALL_COUNT: Cell<u64> = const { Cell::new(0) };
160 static LAST_SEED: Cell<u64> = const { Cell::new(0) };
161 }
162
163 set_rng_hooks(
164 || CALL_COUNT.with(|c| c.get()),
165 |seed| LAST_SEED.with(|s| s.set(seed)),
166 );
167
168 CALL_COUNT.with(|c| c.set(42));
169 assert_eq!(rng_get_count(), 42);
170
171 rng_reseed(123);
172 assert_eq!(LAST_SEED.with(|s| s.get()), 123);
173
174 set_rng_hooks(|| 0, |_| {});
176 }
177
178 #[test]
179 fn test_inactive_by_default() {
180 assert!(!explorer_is_active());
181 assert!(!explorer_is_child());
182 }
183}