use crate::futures::task::{Task, sealed};
use crate::modules::input::Token;
use std::{fmt, marker::PhantomData};
#[must_use = "a task does nothing until it is run or spawned"]
pub struct ComputeTask<F, V, T> {
work: F,
input: Option<V>,
blocking: bool,
_output: PhantomData<fn() -> T>,
}
impl<F, V, T> ComputeTask<F, V, T> {
pub(crate) fn new(work: F) -> Self {
Self {
work,
input: None,
blocking: false,
_output: PhantomData,
}
}
pub fn blocking(mut self) -> Self {
self.blocking = true;
self
}
}
impl<F, V, T> Clone for ComputeTask<F, V, T>
where
F: Clone,
V: Clone,
{
fn clone(&self) -> Self {
Self {
work: self.work.clone(),
input: self.input.clone(),
blocking: self.blocking,
_output: PhantomData,
}
}
}
impl<F, V, T> fmt::Debug for ComputeTask<F, V, T> {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("ComputeTask")
.field("given", &self.input.is_some())
.field("blocking", &self.blocking)
.finish_non_exhaustive()
}
}
impl<F, V, T> sealed::Sealed for ComputeTask<F, V, T> {}
impl<F, V, T> Task for ComputeTask<F, V, T>
where
F: Fn(V) -> T + Send + 'static,
V: Clone + Send + 'static,
T: Send + 'static,
{
type Output = T;
type Input = V;
fn execute(&self, _token: Token, _reactor_id: i32, _task_id: usize) -> Self::Output {
let input = self
.input
.clone()
.expect("a compute only runs once it has been given its input");
(self.work)(input)
}
fn blocking(&self, _token: Token) -> bool {
self.blocking
}
fn give(&mut self, _token: Token, input: Self::Input) {
self.input = Some(input);
}
}