//! Cross-platform helper for preventing idle sleep while a turn is running. //! //! Platform-specific behavior: //! - macOS: Uses native IOKit power assertions instead of spawning `caffeinate`. //! - Linux: Spawns `systemd-inhibit` or `gnome-session-inhibit` while active. //! - Windows: Uses `PowerCreateRequest` + `PowerSetRequest` with //! `PowerRequestSystemRequired`. //! - Other platforms: No-op backend. #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))] mod dummy; #[cfg(target_os = "linux")] mod linux_inhibitor; #[cfg(target_os = "macos")] mod macos; #[cfg(target_os = "windows")] mod windows_inhibitor; #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))] use dummy as imp; #[cfg(target_os = "linux")] use linux_inhibitor as imp; #[cfg(target_os = "macos")] use macos as imp; #[cfg(target_os = "windows")] use windows_inhibitor as imp; /// Keeps the machine awake while a turn is in progress when enabled. #[derive(Debug)] pub struct SleepInhibitor { enabled: bool, turn_running: bool, platform: imp::SleepInhibitor, } impl SleepInhibitor { pub fn new(enabled: bool) -> Self { Self { enabled, turn_running: false, platform: imp::SleepInhibitor::new(), } } /// Update the active turn state; turns sleep prevention on/off as needed. pub fn set_turn_running(&mut self, turn_running: bool) { self.turn_running = turn_running; if !self.enabled { self.release(); return; } if turn_running { self.acquire(); } else { self.release(); } } fn acquire(&mut self) { self.platform.acquire(); } fn release(&mut self) { self.platform.release(); } /// Return the latest turn-running state requested by the caller. pub fn is_turn_running(&self) -> bool { self.turn_running } } #[cfg(test)] mod tests { use super::SleepInhibitor; #[test] fn sleep_inhibitor_toggles_without_panicking() { let mut inhibitor = SleepInhibitor::new(true); inhibitor.set_turn_running(true); assert!(inhibitor.is_turn_running()); inhibitor.set_turn_running(false); assert!(!inhibitor.is_turn_running()); } #[test] fn sleep_inhibitor_disabled_does_not_panic() { let mut inhibitor = SleepInhibitor::new(false); inhibitor.set_turn_running(true); assert!(inhibitor.is_turn_running()); inhibitor.set_turn_running(false); assert!(!inhibitor.is_turn_running()); } #[test] fn sleep_inhibitor_multiple_true_calls_are_idempotent() { let mut inhibitor = SleepInhibitor::new(true); inhibitor.set_turn_running(true); inhibitor.set_turn_running(true); inhibitor.set_turn_running(true); inhibitor.set_turn_running(false); } #[test] fn sleep_inhibitor_can_toggle_multiple_times() { let mut inhibitor = SleepInhibitor::new(true); inhibitor.set_turn_running(true); inhibitor.set_turn_running(false); inhibitor.set_turn_running(true); inhibitor.set_turn_running(false); } }