use std::sync::atomic::{AtomicU8, Ordering};
use super::thread_pool_lifecycle::ThreadPoolLifecycle;
const LIFECYCLE_RUNNING: u8 = 0;
const LIFECYCLE_SHUTDOWN: u8 = 1;
const LIFECYCLE_STOPPING: u8 = 2;
fn encode_lifecycle(lifecycle: ThreadPoolLifecycle) -> u8 {
match lifecycle {
ThreadPoolLifecycle::Running => LIFECYCLE_RUNNING,
ThreadPoolLifecycle::Shutdown => LIFECYCLE_SHUTDOWN,
ThreadPoolLifecycle::Stopping => LIFECYCLE_STOPPING,
}
}
fn decode_lifecycle(tag: u8) -> ThreadPoolLifecycle {
match tag {
LIFECYCLE_RUNNING => ThreadPoolLifecycle::Running,
LIFECYCLE_SHUTDOWN => ThreadPoolLifecycle::Shutdown,
LIFECYCLE_STOPPING => ThreadPoolLifecycle::Stopping,
_ => panic!("invalid thread pool lifecycle tag: {tag}"),
}
}
pub(super) struct LifecycleStateMachine {
state: AtomicU8,
}
impl LifecycleStateMachine {
pub(super) fn new_running() -> Self {
Self {
state: AtomicU8::new(encode_lifecycle(ThreadPoolLifecycle::Running)),
}
}
pub(super) fn load(&self) -> ThreadPoolLifecycle {
decode_lifecycle(self.state.load(Ordering::Acquire))
}
pub(super) fn transition_running_to_shutdown(&self) -> bool {
self.state
.compare_exchange(
LIFECYCLE_RUNNING,
LIFECYCLE_SHUTDOWN,
Ordering::AcqRel,
Ordering::Acquire,
)
.is_ok()
}
pub(super) fn transition_to_stopping(&self) -> bool {
loop {
let current = self.state.load(Ordering::Acquire);
if current == LIFECYCLE_STOPPING {
return false;
}
if self
.state
.compare_exchange(
current,
LIFECYCLE_STOPPING,
Ordering::AcqRel,
Ordering::Acquire,
)
.is_ok()
{
return true;
}
}
}
}