use std::sync::atomic::{AtomicU8, Ordering};
use std::sync::Arc;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum WarmupState {
Cold = 0,
Resurrecting = 1,
Ready = 2,
}
impl From<u8> for WarmupState {
fn from(v: u8) -> Self {
match v {
0 => Self::Cold,
1 => Self::Resurrecting,
2 => Self::Ready,
_ => Self::Cold,
}
}
}
#[derive(Clone)]
pub struct WarmupTracker {
state: Arc<AtomicU8>,
}
impl WarmupTracker {
pub fn new() -> Self {
Self {
state: Arc::new(AtomicU8::new(WarmupState::Cold as u8)),
}
}
pub fn state(&self) -> WarmupState {
WarmupState::from(self.state.load(Ordering::SeqCst))
}
pub fn is_ready(&self) -> bool {
matches!(self.state(), WarmupState::Cold | WarmupState::Ready)
}
pub fn begin_resurrection(&self) {
self.state
.store(WarmupState::Resurrecting as u8, Ordering::SeqCst);
}
pub fn mark_ready(&self) {
self.state.store(WarmupState::Ready as u8, Ordering::SeqCst);
}
pub fn mark_cold(&self) {
self.state.store(WarmupState::Cold as u8, Ordering::SeqCst);
}
}
impl Default for WarmupTracker {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_warmup_state_transitions() {
let tracker = WarmupTracker::new();
assert_eq!(tracker.state(), WarmupState::Cold);
assert!(tracker.is_ready());
tracker.begin_resurrection();
assert_eq!(tracker.state(), WarmupState::Resurrecting);
assert!(!tracker.is_ready());
tracker.mark_ready();
assert_eq!(tracker.state(), WarmupState::Ready);
assert!(tracker.is_ready());
}
}