#[cfg(not(all(windows, not(alloc_frugal))))]
use core::time::Duration;
use crate::platform::types::{FRAME_INTERVAL_MS, IDLE_FRAME_INTERVAL_MS};
#[cfg(not(alloc_frugal))]
mod inner {
use core::sync::atomic::{AtomicU64, Ordering};
use core::time::Duration;
use std::sync::{Condvar, Mutex, OnceLock};
struct WakeState {
generation: AtomicU64,
mutex: Mutex<()>,
ready: Condvar,
}
static WAKE: OnceLock<WakeState> = OnceLock::new();
fn state() -> &'static WakeState {
WAKE.get_or_init(|| WakeState {
generation: AtomicU64::new(0),
mutex: Mutex::new(()),
ready: Condvar::new(),
})
}
pub(crate) fn wake() {
let state = state();
state.generation.fetch_add(1, Ordering::SeqCst);
let _guard = state.mutex.lock().unwrap_or_else(|poisoned| poisoned.into_inner());
state.ready.notify_all();
}
#[allow(dead_code)]
pub(crate) fn wait_timeout(timeout: Duration) {
let state = state();
let observed = state.generation.load(Ordering::SeqCst);
let guard = state.mutex.lock().unwrap_or_else(|poisoned| poisoned.into_inner());
if state.generation.load(Ordering::SeqCst) != observed {
return;
}
let _ = state.ready.wait_timeout(guard, timeout);
}
pub(crate) fn generation() -> u64 {
state().generation.load(Ordering::SeqCst)
}
pub(crate) fn wait_after(observed: u64, timeout: Duration) {
let state = state();
let guard = state.mutex.lock().unwrap_or_else(|poisoned| poisoned.into_inner());
if state.generation.load(Ordering::SeqCst) != observed {
return;
}
let _ = state.ready.wait_timeout(guard, timeout);
}
}
#[cfg(alloc_frugal)]
mod inner {
use core::time::Duration;
pub(crate) fn wake() {}
pub(crate) fn wait_timeout(timeout: Duration) {
std::thread::sleep(timeout);
}
}
pub(crate) use inner::wake;
#[cfg(not(alloc_frugal))]
pub(crate) use inner::{generation, wait_after};
pub(crate) fn pause_between_frames(needs_another_frame: bool) {
#[cfg(all(windows, not(alloc_frugal)))]
{
let timeout = if needs_another_frame { FRAME_INTERVAL_MS } else { IDLE_FRAME_INTERVAL_MS };
unsafe {
winapi::um::winuser::MsgWaitForMultipleObjectsEx(
0,
core::ptr::null(),
timeout as u32,
winapi::um::winuser::QS_ALLINPUT,
winapi::um::winuser::MWMO_INPUTAVAILABLE,
);
}
}
#[cfg(not(all(windows, not(alloc_frugal))))]
{
let timeout = if needs_another_frame { FRAME_INTERVAL_MS } else { IDLE_FRAME_INTERVAL_MS };
inner::wait_timeout(Duration::from_millis(timeout));
}
}