use oneshot::{
Receiver,
TryRecvError,
};
use std::{
future::IntoFuture,
sync::Arc,
};
use super::{
TaskExecutionError,
TaskResult,
task_handle_future::TaskHandleFuture,
task_result_handle::TaskResultHandle,
task_state::TaskState,
try_get::TryGet,
};
use crate::hook::TaskId;
pub struct TaskHandle<R, E> {
pub(crate) state: Arc<TaskState<R, E>>,
receiver: Receiver<TaskResult<R, E>>,
}
impl<R, E> TaskHandle<R, E> {
#[inline]
pub(crate) const fn new(
state: Arc<TaskState<R, E>>,
receiver: Receiver<TaskResult<R, E>>,
) -> Self {
Self { state, receiver }
}
#[inline]
pub fn task_id(&self) -> TaskId {
self.state.task_id
}
#[inline]
pub(crate) fn accept(&self) {
let _accepted_now = self.state.accept();
}
#[inline]
pub fn get(self) -> TaskResult<R, E> {
self.receiver
.recv()
.unwrap_or(Err(TaskExecutionError::Dropped))
}
#[inline]
pub fn try_get(self) -> TryGet<Self, R, E> {
let Self { state, receiver } = self;
match receiver.try_recv() {
Ok(result) => TryGet::Ready(result),
Err(TryRecvError::Empty) => TryGet::Pending(Self { state, receiver }),
Err(TryRecvError::Disconnected) => TryGet::Ready(Err(TaskExecutionError::Dropped)),
}
}
#[inline]
pub fn is_done(&self) -> bool {
self.state.status().is_done()
}
}
impl<R, E> TaskResultHandle<R, E> for TaskHandle<R, E>
where
R: Send,
E: Send,
{
#[inline]
fn is_done(&self) -> bool {
Self::is_done(self)
}
#[inline]
fn get(self) -> TaskResult<R, E> {
Self::get(self)
}
#[inline]
fn try_get(self) -> TryGet<Self, R, E> {
Self::try_get(self)
}
}
impl<R, E> IntoFuture for TaskHandle<R, E> {
type Output = TaskResult<R, E>;
type IntoFuture = TaskHandleFuture<R, E>;
#[inline]
fn into_future(self) -> Self::IntoFuture {
TaskHandleFuture::new(IntoFuture::into_future(self.receiver))
}
}