use std::{
future::IntoFuture,
sync::{
Arc,
atomic::{
AtomicBool,
Ordering,
},
},
};
use crate::{
CancelResult,
TaskResult,
TaskStatus,
TrackedTask,
TryGet,
hook::TaskId,
task::{
TaskHandleFuture,
spi::{
TaskResultHandle,
TrackedTaskHandle,
},
},
};
pub struct ScheduledTaskHandle<R, E> {
inner: TrackedTask<R, E>,
cancellation_marker: Arc<AtomicBool>,
on_cancelled: Arc<dyn Fn() + Send + Sync + 'static>,
}
impl<R, E> ScheduledTaskHandle<R, E> {
pub(crate) const fn new(
inner: TrackedTask<R, E>,
cancellation_marker: Arc<AtomicBool>,
on_cancelled: Arc<dyn Fn() + Send + Sync + 'static>,
) -> Self {
Self {
inner,
cancellation_marker,
on_cancelled,
}
}
#[inline]
pub fn get(self) -> TaskResult<R, E>
where
R: Send,
E: Send,
{
<Self as TaskResultHandle<R, E>>::get(self)
}
#[inline]
pub fn try_get(self) -> TryGet<Self, R, E>
where
R: Send,
E: Send,
{
<Self as TaskResultHandle<R, E>>::try_get(self)
}
#[inline]
pub fn is_done(&self) -> bool
where
R: Send,
E: Send,
{
<Self as TaskResultHandle<R, E>>::is_done(self)
}
#[inline]
pub fn status(&self) -> TaskStatus {
self.inner.status()
}
#[inline]
pub fn task_id(&self) -> TaskId {
self.inner.task_id()
}
#[inline]
pub fn cancel(&self) -> CancelResult {
self.cancel_inner()
}
fn cancel_inner(&self) -> CancelResult {
let result = self.inner.cancel();
if result == CancelResult::Cancelled {
self.cancellation_marker.store(true, Ordering::Release);
(self.on_cancelled)();
}
result
}
}
impl<R, E> TaskResultHandle<R, E> for ScheduledTaskHandle<R, E>
where
R: Send,
E: Send,
{
#[inline]
fn is_done(&self) -> bool {
self.inner.is_done()
}
#[inline]
fn get(self) -> TaskResult<R, E> {
self.inner.get()
}
#[inline]
fn try_get(self) -> TryGet<Self, R, E> {
let Self {
inner,
cancellation_marker,
on_cancelled,
} = self;
match inner.try_get() {
TryGet::Ready(result) => TryGet::Ready(result),
TryGet::Pending(inner) => TryGet::Pending(Self {
inner,
cancellation_marker,
on_cancelled,
}),
}
}
}
impl<R, E> TrackedTaskHandle<R, E> for ScheduledTaskHandle<R, E>
where
R: Send,
E: Send,
{
#[inline]
fn status(&self) -> TaskStatus {
self.inner.status()
}
#[inline]
fn cancel(&self) -> CancelResult {
self.cancel_inner()
}
}
impl<R, E> IntoFuture for ScheduledTaskHandle<R, E> {
type Output = TaskResult<R, E>;
type IntoFuture = TaskHandleFuture<R, E>;
#[inline]
fn into_future(self) -> Self::IntoFuture {
self.inner.into_future()
}
}