use std::{mem::ManuallyDrop, ptr::NonNull, time::Duration};
use moirai_core::Priority;
use super::state::TaskState;
#[derive(Debug)]
pub(crate) struct TaskLifecycleToken {
pub(super) state: NonNull<TaskState>,
}
#[derive(Debug)]
pub(crate) struct RunningTaskToken {
pub(super) state: NonNull<TaskState>,
pub(super) started_after_ns: u64,
pub(super) completed: bool,
}
unsafe impl Send for TaskLifecycleToken {}
unsafe impl Send for RunningTaskToken {}
impl TaskLifecycleToken {
#[inline]
pub(crate) fn set_priority(&self, priority: Priority) {
unsafe { self.state.as_ref().set_priority(priority) }
}
#[inline]
pub(crate) fn cancel_requested(&self) -> bool {
unsafe { self.state.as_ref().cancel_requested() }
}
#[inline]
pub(crate) fn cancel(self) {
let token = ManuallyDrop::new(self);
unsafe { token.state.as_ref().mark_cancelled() }
}
#[inline]
pub(crate) fn start_unless_cancelled(self, worker_id: usize) -> Option<RunningTaskToken> {
if self.cancel_requested() {
self.cancel();
None
} else {
Some(self.start(worker_id))
}
}
#[inline]
pub(crate) fn start(self, worker_id: usize) -> RunningTaskToken {
let token = ManuallyDrop::new(self);
let state = token.state;
let started_after_ns = unsafe { state.as_ref().mark_started(worker_id) };
RunningTaskToken {
state,
started_after_ns,
completed: false,
}
}
}
impl Drop for TaskLifecycleToken {
fn drop(&mut self) {
unsafe { self.state.as_ref().mark_completed() }
}
}
impl RunningTaskToken {
#[inline]
pub(crate) fn complete(self) -> Duration {
let mut token = ManuallyDrop::new(self);
token.completed = true;
unsafe {
token
.state
.as_ref()
.mark_completed_since(token.started_after_ns)
}
}
#[inline]
pub(super) fn complete_once(&mut self) -> Option<Duration> {
if !self.completed {
let execution_time = unsafe {
self.state
.as_ref()
.mark_completed_since(self.started_after_ns)
};
self.completed = true;
Some(execution_time)
} else {
None
}
}
}
impl Drop for RunningTaskToken {
fn drop(&mut self) {
self.complete_once();
}
}