use std::sync::{
Arc,
atomic::{AtomicBool, AtomicU8, Ordering},
};
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
#[repr(u8)]
pub enum NodeState {
#[default]
Idle = 0,
Starting = 1,
Running = 2,
ShuttingDown = 3,
Stopped = 4,
}
impl NodeState {
#[must_use]
pub const fn from_u8(value: u8) -> Self {
match value {
0 => Self::Idle,
1 => Self::Starting,
2 => Self::Running,
3 => Self::ShuttingDown,
4 => Self::Stopped,
_ => panic!("Invalid NodeState value"),
}
}
#[must_use]
pub const fn as_u8(self) -> u8 {
self as u8
}
#[must_use]
pub const fn is_running(&self) -> bool {
matches!(self, Self::Running)
}
}
#[derive(Clone, Debug)]
pub struct LiveNodeHandle {
pub(crate) stop_flag: Arc<AtomicBool>,
pub(crate) state: Arc<AtomicU8>,
}
impl Default for LiveNodeHandle {
fn default() -> Self {
Self::new()
}
}
impl LiveNodeHandle {
#[must_use]
pub fn new() -> Self {
Self {
stop_flag: Arc::new(AtomicBool::new(false)),
state: Arc::new(AtomicU8::new(NodeState::Idle.as_u8())),
}
}
pub(crate) fn set_state(&self, state: NodeState) {
self.state.store(state.as_u8(), Ordering::Relaxed);
if state == NodeState::Running {
self.stop_flag.store(false, Ordering::Relaxed);
}
}
#[must_use]
pub fn state(&self) -> NodeState {
NodeState::from_u8(self.state.load(Ordering::Relaxed))
}
#[must_use]
pub fn should_stop(&self) -> bool {
self.stop_flag.load(Ordering::Relaxed)
}
#[must_use]
pub fn is_running(&self) -> bool {
self.state().is_running()
}
pub fn stop(&self) {
self.stop_flag.store(true, Ordering::Relaxed);
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(super) enum EngineConnectionStatus {
Connected,
TimedOut,
StopRequested,
ShutdownRequested,
}
impl EngineConnectionStatus {
pub(super) const fn abort_reason(self) -> Option<&'static str> {
match self {
Self::Connected | Self::TimedOut => None,
Self::StopRequested => Some("Stop signal received during startup"),
Self::ShutdownRequested => Some("Shutdown signal received during startup"),
}
}
}