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 ENERGY_BUDGET_PTR: Cell<*mut EnergyBudget> = const { Cell::new(std::ptr::null_mut()) };
39
40 pub(crate) static BITMAP_POOL: Cell<*mut u8> = const { Cell::new(std::ptr::null_mut()) };
42
43 pub(crate) static BITMAP_POOL_SLOTS: Cell<usize> = const { Cell::new(0) };
45}
46
47pub struct ExplorerCtx {
49 pub active: bool,
51 pub is_child: bool,
53 pub depth: u32,
55 pub max_depth: u32,
57 pub current_seed: u64,
59 pub recipe: Vec<(u64, u64)>,
62 pub timelines_per_split: u32,
64 pub adaptive: Option<AdaptiveConfig>,
66 pub parallelism: Option<Parallelism>,
68 pub warm_start: bool,
70}
71
72impl ExplorerCtx {
73 #[must_use]
75 pub fn inactive() -> Self {
76 Self {
77 active: false,
78 is_child: false,
79 depth: 0,
80 max_depth: 0,
81 current_seed: 0,
82 recipe: Vec::new(),
83 timelines_per_split: 0,
84 adaptive: None,
85 parallelism: None,
86 warm_start: false,
87 }
88 }
89}
90
91pub fn set_rng_hooks(get_count: fn() -> u64, reseed: fn(u64)) {
98 RNG_GET_COUNT.with(|c| c.set(get_count));
99 RNG_RESEED.with(|c| c.set(reseed));
100}
101
102pub(crate) fn rng_get_count() -> u64 {
104 RNG_GET_COUNT.with(|c| (c.get())())
105}
106
107pub(crate) fn rng_reseed(seed: u64) {
109 RNG_RESEED.with(|c| (c.get())(seed));
110}
111
112pub(crate) fn with_ctx<R>(f: impl FnOnce(&ExplorerCtx) -> R) -> R {
114 EXPLORER_CTX.with(|ctx| f(&ctx.borrow()))
115}
116
117pub(crate) fn with_ctx_mut<R>(f: impl FnOnce(&mut ExplorerCtx) -> R) -> R {
119 EXPLORER_CTX.with(|ctx| f(&mut ctx.borrow_mut()))
120}
121
122#[must_use]
124pub fn explorer_is_active() -> bool {
125 with_ctx(|ctx| ctx.active)
126}
127
128#[must_use]
130pub fn explorer_is_child() -> bool {
131 with_ctx(|ctx| ctx.is_child)
132}
133
134#[cfg(test)]
135mod tests {
136 use super::*;
137
138 #[test]
139 fn test_default_hooks() {
140 assert_eq!(rng_get_count(), 0);
142 rng_reseed(42);
144 }
145
146 #[test]
147 fn test_set_hooks() {
148 thread_local! {
149 static CALL_COUNT: Cell<u64> = const { Cell::new(0) };
150 static LAST_SEED: Cell<u64> = const { Cell::new(0) };
151 }
152
153 set_rng_hooks(
154 || CALL_COUNT.with(std::cell::Cell::get),
155 |seed| LAST_SEED.with(|s| s.set(seed)),
156 );
157
158 CALL_COUNT.with(|c| c.set(42));
159 assert_eq!(rng_get_count(), 42);
160
161 rng_reseed(123);
162 assert_eq!(LAST_SEED.with(std::cell::Cell::get), 123);
163
164 set_rng_hooks(|| 0, |_| {});
166 }
167
168 #[test]
169 fn test_inactive_by_default() {
170 assert!(!explorer_is_active());
171 assert!(!explorer_is_child());
172 }
173}