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 #[must_use]
81 pub fn inactive() -> Self {
82 Self {
83 active: false,
84 is_child: false,
85 depth: 0,
86 max_depth: 0,
87 current_seed: 0,
88 recipe: Vec::new(),
89 timelines_per_split: 0,
90 adaptive: None,
91 parallelism: None,
92 warm_start: false,
93 }
94 }
95}
96
97pub fn set_rng_hooks(get_count: fn() -> u64, reseed: fn(u64)) {
104 RNG_GET_COUNT.with(|c| c.set(get_count));
105 RNG_RESEED.with(|c| c.set(reseed));
106}
107
108pub(crate) fn rng_get_count() -> u64 {
110 RNG_GET_COUNT.with(|c| (c.get())())
111}
112
113pub(crate) fn rng_reseed(seed: u64) {
115 RNG_RESEED.with(|c| (c.get())(seed));
116}
117
118pub(crate) fn with_ctx<R>(f: impl FnOnce(&ExplorerCtx) -> R) -> R {
120 EXPLORER_CTX.with(|ctx| f(&ctx.borrow()))
121}
122
123pub(crate) fn with_ctx_mut<R>(f: impl FnOnce(&mut ExplorerCtx) -> R) -> R {
125 EXPLORER_CTX.with(|ctx| f(&mut ctx.borrow_mut()))
126}
127
128#[must_use]
130pub fn explorer_is_active() -> bool {
131 with_ctx(|ctx| ctx.active)
132}
133
134#[must_use]
136pub fn explorer_is_child() -> bool {
137 with_ctx(|ctx| ctx.is_child)
138}
139
140#[must_use]
144pub fn assertion_table_ptr() -> *mut u8 {
145 ASSERTION_TABLE.with(std::cell::Cell::get)
146}
147
148#[cfg(test)]
149mod tests {
150 use super::*;
151
152 #[test]
153 fn test_default_hooks() {
154 assert_eq!(rng_get_count(), 0);
156 rng_reseed(42);
158 }
159
160 #[test]
161 fn test_set_hooks() {
162 thread_local! {
163 static CALL_COUNT: Cell<u64> = const { Cell::new(0) };
164 static LAST_SEED: Cell<u64> = const { Cell::new(0) };
165 }
166
167 set_rng_hooks(
168 || CALL_COUNT.with(std::cell::Cell::get),
169 |seed| LAST_SEED.with(|s| s.set(seed)),
170 );
171
172 CALL_COUNT.with(|c| c.set(42));
173 assert_eq!(rng_get_count(), 42);
174
175 rng_reseed(123);
176 assert_eq!(LAST_SEED.with(std::cell::Cell::get), 123);
177
178 set_rng_hooks(|| 0, |_| {});
180 }
181
182 #[test]
183 fn test_inactive_by_default() {
184 assert!(!explorer_is_active());
185 assert!(!explorer_is_child());
186 }
187}