use std::fmt::Write as _;
use super::tick_wake::{ALL, WakeSnapshot};
pub const TICK_HEARTBEAT_FRAMES: u32 = 30;
pub const TICK_GATE_WARMUP_FRAMES: u32 = 600;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TickGateInputs {
pub bits: u32,
pub deadline_due: bool,
pub frames_since_run: u32,
pub frames_since_boot: u32,
pub gate_enabled: bool,
}
impl TickGateInputs {
#[inline]
pub fn from_snapshot(
snapshot: &WakeSnapshot,
frames_since_run: u32,
frames_since_boot: u32,
gate_enabled: bool,
) -> TickGateInputs {
TickGateInputs {
bits: snapshot.bits,
deadline_due: snapshot.deadline_due,
frames_since_run,
frames_since_boot,
gate_enabled,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RunReason {
Disabled,
Warmup,
Wake(u32),
Deadline,
Heartbeat,
}
impl RunReason {
#[inline]
pub fn as_str(&self) -> &'static str {
match self {
RunReason::Disabled => "disabled",
RunReason::Warmup => "warmup",
RunReason::Wake(_) => "wake",
RunReason::Deadline => "deadline",
RunReason::Heartbeat => "heartbeat",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TickDecision {
Run(RunReason),
Skip,
}
impl TickDecision {
#[inline]
pub fn is_run(&self) -> bool {
matches!(self, TickDecision::Run(_))
}
}
#[inline]
pub fn should_run(i: &TickGateInputs) -> TickDecision {
if !i.gate_enabled {
return TickDecision::Run(RunReason::Disabled);
}
if i.frames_since_boot < TICK_GATE_WARMUP_FRAMES {
return TickDecision::Run(RunReason::Warmup);
}
if i.bits != 0 {
return TickDecision::Run(RunReason::Wake(i.bits));
}
if i.deadline_due {
return TickDecision::Run(RunReason::Deadline);
}
if i.frames_since_run >= TICK_HEARTBEAT_FRAMES {
return TickDecision::Run(RunReason::Heartbeat);
}
TickDecision::Skip
}
pub fn wake_names(bits: u32) -> String {
if bits == 0 {
return "NONE".to_string();
}
let mut out = String::new();
let mut rest = bits;
for (name, flag) in ALL {
if bits & flag.bits() != 0 {
if !out.is_empty() {
out.push('|');
}
out.push_str(name);
rest &= !flag.bits();
}
}
if rest != 0 {
if !out.is_empty() {
out.push('|');
}
let _ = write!(out, "{rest:#x}");
}
out
}
#[cfg(test)]
#[path = "tick_gate_tests.rs"]
mod tests;