use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::RwLock;
struct GradMode {
enabled_stack: Vec<bool>,
current_enabled: bool,
}
impl GradMode {
const fn new() -> Self {
Self {
enabled_stack: Vec::new(),
current_enabled: true,
}
}
}
static GRAD_MODE: RwLock<GradMode> = RwLock::new(GradMode::new());
static GRAD_ENABLED: AtomicBool = AtomicBool::new(true);
fn with_mode<R>(f: impl FnOnce(&mut GradMode) -> R) -> R {
let mut mode = match GRAD_MODE.write() {
Ok(guard) => guard,
Err(poisoned) => poisoned.into_inner(),
};
let result = f(&mut mode);
GRAD_ENABLED.store(mode.current_enabled, Ordering::Relaxed);
result
}
#[inline]
pub fn is_grad_enabled() -> bool {
GRAD_ENABLED.load(Ordering::Relaxed)
}
pub fn set_grad_enabled(enabled: bool) {
with_mode(|mode| {
mode.current_enabled = enabled;
mode.enabled_stack.clear();
});
}
pub fn push_grad_enabled(enabled: bool) {
with_mode(|mode| {
mode.enabled_stack.push(mode.current_enabled);
mode.current_enabled = enabled;
});
}
pub fn pop_grad_enabled() {
with_mode(|mode| {
if let Some(previous) = mode.enabled_stack.pop() {
mode.current_enabled = previous;
}
});
}
pub fn with_grad_mode<F, R>(enabled: bool, f: F) -> R
where
F: FnOnce() -> R,
{
push_grad_enabled(enabled);
let result = f();
pop_grad_enabled();
result
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::{Mutex, MutexGuard};
static TEST_LOCK: Mutex<()> = Mutex::new(());
fn serial() -> MutexGuard<'static, ()> {
let guard = match TEST_LOCK.lock() {
Ok(guard) => guard,
Err(poisoned) => poisoned.into_inner(),
};
set_grad_enabled(true);
guard
}
#[test]
fn default_is_enabled() {
let _serial = serial();
assert!(is_grad_enabled());
}
#[test]
fn push_pop_restores_previous_state() {
let _serial = serial();
push_grad_enabled(false);
assert!(!is_grad_enabled());
push_grad_enabled(true);
assert!(is_grad_enabled());
pop_grad_enabled();
assert!(!is_grad_enabled());
pop_grad_enabled();
assert!(is_grad_enabled());
}
#[test]
fn set_clears_nesting() {
let _serial = serial();
push_grad_enabled(false);
set_grad_enabled(true);
pop_grad_enabled();
assert!(is_grad_enabled());
}
#[test]
fn with_grad_mode_scopes_the_change() {
let _serial = serial();
let observed = with_grad_mode(false, is_grad_enabled);
assert!(!observed);
assert!(is_grad_enabled());
}
#[test]
fn state_is_visible_across_threads() {
let _serial = serial();
push_grad_enabled(false);
let observed = std::thread::spawn(is_grad_enabled)
.join()
.unwrap_or_else(|_| panic!("observer thread panicked"));
pop_grad_enabled();
assert!(!observed, "gradient mode must stay process-global");
}
}