use std::mem::ManuallyDrop;
use tokio::sync::watch;
use tokio::task::JoinHandle;
use super::ConnectionError;
use crate::Result;
#[non_exhaustive]
pub struct MonitorHandle {
shutdown_tx: watch::Sender<()>,
task: ManuallyDrop<JoinHandle<Result<()>>>,
}
impl MonitorHandle {
pub(crate) fn new(shutdown_tx: watch::Sender<()>, task: JoinHandle<Result<()>>) -> Self {
Self {
shutdown_tx,
task: ManuallyDrop::new(task),
}
}
pub async fn stop(mut self) -> Result<()> {
let _ = self.shutdown_tx.send(());
let task = unsafe { ManuallyDrop::take(&mut self.task) };
std::mem::forget(self);
task.await
.map_err(|e| ConnectionError::Stuck(format!("monitor task panicked: {e}")))?
}
pub fn shutdown(&self) {
let _ = self.shutdown_tx.send(());
}
}
impl Drop for MonitorHandle {
fn drop(&mut self) {
let _ = self.shutdown_tx.send(());
}
}