2026-07-11 23:45:13 +07:00
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
pub struct EventLoop {
|
|
|
|
|
last_activity: Instant,
|
|
|
|
|
fast_poll_until: Option<Instant>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl EventLoop {
|
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
EventLoop {
|
|
|
|
|
last_activity: Instant::now(),
|
|
|
|
|
fast_poll_until: None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn mark_active(&mut self) {
|
|
|
|
|
self.last_activity = Instant::now();
|
|
|
|
|
self.fast_poll_until = Some(Instant::now() + Duration::from_millis(IDLE_THRESHOLD_MS));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn is_idle(&self) -> bool {
|
|
|
|
|
self.last_activity.elapsed().as_millis() as u64 > IDLE_THRESHOLD_MS
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
}
|
|
|
|
|
}
|