use tokio::{sync::Mutex, task::JoinHandle};
use crate::events::{Bus, Event};
pub(super) struct ControllerTask {
state: Mutex<ControllerTaskState>,
}
enum ControllerTaskState {
Running(JoinHandle<()>),
Joined(bool),
}
impl ControllerTask {
pub(super) fn new(handle: JoinHandle<()>) -> Self {
Self {
state: Mutex::new(ControllerTaskState::Running(handle)),
}
}
pub(super) async fn join(&self, bus: &Bus) -> bool {
let mut state = self.state.lock().await;
if let ControllerTaskState::Joined(clean) = &*state {
return *clean;
}
let ControllerTaskState::Running(handle) = &mut *state else {
unreachable!("joined controller state was returned above")
};
let clean = match handle.await {
Ok(()) => true,
Err(error) => {
bus.publish(Event::runtime_failure(
"controller",
format!("controller_join_failed: {error}"),
));
false
}
};
*state = ControllerTaskState::Joined(clean);
clean
}
#[cfg(test)]
pub(super) async fn is_joined(&self) -> bool {
matches!(*self.state.lock().await, ControllerTaskState::Joined(_))
}
#[cfg(test)]
pub(super) fn state_is_locked(&self) -> bool {
self.state.try_lock().is_err()
}
}