blob: 5e454141c2fea41e1b2be8f5bb70d105be261c89 [file] [log] [blame]
//! Scheduler for emitting events at a specific time in the future.
use std::collections::VecDeque;
use std::time::{Duration, Instant};
use glutin::event::Event as GlutinEvent;
use crate::event::Event as AlacrittyEvent;
type Event = GlutinEvent<'static, AlacrittyEvent>;
/// ID uniquely identifying a timer.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum TimerId {
SelectionScrolling,
DelayedSearch,
BlinkCursor,
}
/// Event scheduled to be emitted at a specific time.
pub struct Timer {
pub deadline: Instant,
pub event: Event,
interval: Option<Duration>,
id: TimerId,
}
/// Scheduler tracking all pending timers.
pub struct Scheduler {
timers: VecDeque<Timer>,
}
impl Default for Scheduler {
fn default() -> Self {
Self { timers: VecDeque::new() }
}
}
impl Scheduler {
pub fn new() -> Self {
Self::default()
}
/// Process all pending timers.
///
/// If there are still timers pending after all ready events have been processed, the closest
/// pending deadline will be returned.
pub fn update(&mut self, event_queue: &mut Vec<Event>) -> Option<Instant> {
let now = Instant::now();
while !self.timers.is_empty() && self.timers[0].deadline <= now {
if let Some(timer) = self.timers.pop_front() {
// Automatically repeat the event.
if let Some(interval) = timer.interval {
self.schedule(timer.event.clone(), interval, true, timer.id);
}
event_queue.push(timer.event);
}
}
self.timers.get(0).map(|timer| timer.deadline)
}
/// Schedule a new event.
pub fn schedule(&mut self, event: Event, interval: Duration, repeat: bool, timer_id: TimerId) {
let deadline = Instant::now() + interval;
// Get insert position in the schedule.
let mut index = self.timers.len();
loop {
if index == 0 {
break;
}
index -= 1;
if self.timers[index].deadline < deadline {
break;
}
}
// Set the automatic event repeat rate.
let interval = if repeat { Some(interval) } else { None };
self.timers.insert(index, Timer { interval, deadline, event, id: timer_id });
}
/// Cancel a scheduled event.
pub fn unschedule(&mut self, id: TimerId) -> Option<Event> {
let index = self.timers.iter().position(|timer| timer.id == id)?;
self.timers.remove(index).map(|timer| timer.event)
}
/// Check if a timer is already scheduled.
pub fn scheduled(&mut self, id: TimerId) -> bool {
self.timers.iter().any(|timer| timer.id == id)
}
/// Access a staged event by ID.
pub fn get_mut(&mut self, id: TimerId) -> Option<&mut Timer> {
self.timers.iter_mut().find(|timer| timer.id == id)
}
}