use std::{future::Future, marker::PhantomData, ptr::NonNull, rc::Rc};
use header::Header;
use raw::RawTask;
use crate::runtime::Schedule;
pub(crate) mod header;
pub(crate) mod internal;
pub(crate) mod join;
pub(crate) mod raw;
pub(crate) mod state;
pub(crate) mod trailer;
mod utils;
mod vtable;
pub(crate) mod waker;
pub use join::{JoinError, JoinHandle};
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub(crate) struct TaskId(NonNull<Header>);
#[repr(transparent)]
pub(crate) struct Task<S: Schedule> {
raw: RawTask,
_p: PhantomData<S>,
}
unsafe impl<S: Schedule> Send for Task<S> {}
unsafe impl<S: Schedule> Sync for Task<S> {}
impl<S: Schedule> Task<S> {
unsafe fn from_raw(task_ptr: NonNull<Header>) -> Task<S> {
Task {
raw: RawTask::from_raw(task_ptr),
_p: PhantomData,
}
}
fn header(&self) -> &Header {
self.raw.header()
}
pub(crate) fn run(self) -> TaskId {
let id = TaskId(self.raw.task_ptr());
let raw = self.raw;
std::mem::forget(self);
raw.poll();
id
}
}
impl<S: Schedule> Drop for Task<S> {
fn drop(&mut self) {
if self.header().state.ref_dec() {
self.raw.dealloc();
}
}
}
pub(crate) struct OwnedTask<S: Schedule> {
raw: RawTask,
_scheduler: PhantomData<S>,
_local: PhantomData<Rc<()>>,
}
impl<S: Schedule> OwnedTask<S> {
fn new(raw: RawTask) -> Self {
raw.header().state.ref_inc();
Self {
raw,
_scheduler: PhantomData,
_local: PhantomData,
}
}
pub(crate) fn id(&self) -> TaskId {
TaskId(self.raw.task_ptr())
}
pub(crate) fn abort(&self) {
self.raw.cancel();
}
pub(crate) fn is_finished(&self) -> bool {
self.raw.header().state.get_snapshot().is_complete()
}
}
impl<S: Schedule> Drop for OwnedTask<S> {
fn drop(&mut self) {
self.raw.drop_reference();
}
}
pub(crate) fn new_task<F, S>(future: F, scheduler: S) -> (Task<S>, JoinHandle<F::Output>)
where
S: Schedule,
F: Future + Send + 'static,
F::Output: Send + 'static,
{
let raw = RawTask::new(future, scheduler);
let task = Task { raw, _p: PhantomData };
let join = JoinHandle::new(raw);
(task, join)
}
pub(crate) fn new_owned_task<F, S>(future: F, scheduler: S) -> (Task<S>, JoinHandle<F::Output>, OwnedTask<S>)
where
S: Schedule,
F: Future + 'static,
F::Output: 'static,
{
let raw = RawTask::new(future, scheduler);
let task = Task { raw, _p: PhantomData };
let join = JoinHandle::new(raw);
let owned = OwnedTask::new(raw);
(task, join, owned)
}