Files
zesdex/crates/zesdex-backend/src/app/runtime/event_loop/mod.rs
T

68 lines
2.2 KiB
Rust
Raw Normal View History

//! Adaptive poll-rate event loop: polls faster for IDLE_THRESHOLD_MS
//! after any activity, then slows down to conserve CPU.
use std::collections::VecDeque;
use std::time::{Duration, Instant};
use crate::app::state::runtime::TurnEvent;
const FAST_POLL_MS: u64 = 8;
const SLOW_POLL_MS: u64 = 100;
const IDLE_THRESHOLD_MS: u64 = 500;
/// Tracks whether the app has been active vs idle to adjust the TUI poll
/// rate, balancing responsiveness against CPU usage.
pub struct EventLoop {
last_activity: Instant,
fast_poll_until: Option<Instant>,
}
impl EventLoop {
/// Create an `EventLoop` with the current instant as the last activity.
pub fn new() -> Self {
EventLoop {
last_activity: Instant::now(),
fast_poll_until: None,
}
}
/// Return the appropriate polling delay based on activity state.
///
/// Flow: if `fast_poll_until` is set and the deadline hasn't expired,
/// return `FAST_POLL_MS`; otherwise return `SLOW_POLL_MS`.
pub fn poll_interval(&self) -> Duration {
if let Some(fast_until) = self.fast_poll_until {
if Instant::now() < fast_until {
return Duration::from_millis(FAST_POLL_MS);
}
}
Duration::from_millis(SLOW_POLL_MS)
}
/// Mark the current time as the last activity and arm the fast-poll
/// window for the next `IDLE_THRESHOLD_MS`.
pub fn mark_active(&mut self) {
self.last_activity = Instant::now();
self.fast_poll_until = Some(Instant::now() + Duration::from_millis(IDLE_THRESHOLD_MS));
}
/// Return `true` if the app has been idle for more than `IDLE_THRESHOLD_MS`.
pub fn is_idle(&self) -> bool {
self.last_activity.elapsed().as_millis() as u64 > IDLE_THRESHOLD_MS
}
/// Drain all pending `TurnEvent`s from the shared mutex queue.
///
/// Return: a `Vec` of all events that were in the queue (may be empty).
pub fn drain_events(
events: &std::sync::Mutex<VecDeque<TurnEvent>>,
) -> Vec<TurnEvent> {
events.lock().map(|mut q| q.drain(..).collect()).unwrap_or_default()
}
}
impl Default for EventLoop {
fn default() -> Self {
Self::new()
}
}