use tokio::task::JoinHandle;
pub trait Abortable {
fn abort(&mut self);
fn is_finished(&self) -> bool;
}
impl Abortable for JoinHandle<()> {
fn abort(&mut self) {
Self::abort(self);
}
fn is_finished(&self) -> bool {
Self::is_finished(self)
}
}
pub trait Stoppable {
fn send(self);
}
impl Stoppable for tokio::sync::oneshot::Sender<()> {
fn send(self) {
let _ = Self::send(self, ());
}
}
pub fn drop_impl<H, S>(inner: &mut Option<H>, stop_tx: &mut Option<S>)
where
H: Abortable,
S: Stoppable,
{
if let Some(tx) = stop_tx.take() {
tx.send();
}
if let Some(mut h) = inner.take()
&& !h.is_finished()
{
h.abort();
}
}
#[derive(Debug)]
pub struct StreamHandle {
inner: Option<tokio::task::JoinHandle<()>>,
stop_tx: Option<tokio::sync::oneshot::Sender<()>>,
}
impl StreamHandle {
#[must_use]
pub const fn new(
inner: tokio::task::JoinHandle<()>,
stop_tx: tokio::sync::oneshot::Sender<()>,
) -> Self {
Self {
inner: Some(inner),
stop_tx: Some(stop_tx),
}
}
#[must_use]
pub const fn new_abort_only(inner: tokio::task::JoinHandle<()>) -> Self {
Self {
inner: Some(inner),
stop_tx: None,
}
}
pub async fn stop(mut self) {
if let Some(tx) = self.stop_tx.take() {
let _ = tx.send(());
}
if let Some(inner) = self.inner.take() {
let _ = inner.await;
}
}
pub fn abort(mut self) {
if let Some(inner) = self.inner.take() {
inner.abort();
}
}
}
impl Drop for StreamHandle {
fn drop(&mut self) {
crate::stream::drop_impl(&mut self.inner, &mut self.stop_tx);
}
}