use core::fmt;
use core::task::Waker;
use crate::task::raw::TaskVTable;
use crate::task::state::*;
use crate::task::utils::abort_on_panic;
use std::thread::ThreadId;
pub(crate) struct Header {
pub(crate) thread_id: ThreadId,
pub(crate) state: usize,
pub(crate) awaiter: Option<Waker>,
pub(crate) vtable: &'static TaskVTable,
}
impl Header {
pub(crate) fn cancel(&mut self) {
if self.state & (COMPLETED | CLOSED) != 0 {
return;
}
self.state |= CLOSED;
}
#[inline]
pub(crate) fn notify(&mut self, current: Option<&Waker>) {
let waker = self.awaiter.take();
self.state &= !AWAITER;
if let Some(w) = waker {
abort_on_panic(|| match current {
None => w.wake(),
Some(c) if !w.will_wake(c) => w.wake(),
Some(_) => {}
});
}
}
#[inline]
pub(crate) fn register(&mut self, waker: &Waker) {
abort_on_panic(|| self.awaiter = Some(waker.clone()));
self.state |= AWAITER;
}
}
impl fmt::Debug for Header {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let state = self.state;
f.debug_struct("Header")
.field("thread_id", &self.thread_id)
.field("scheduled", &(state & SCHEDULED != 0))
.field("running", &(state & RUNNING != 0))
.field("completed", &(state & COMPLETED != 0))
.field("closed", &(state & CLOSED != 0))
.field("awaiter", &(state & AWAITER != 0))
.field("handle", &(state & HANDLE != 0))
.field("ref_count", &(state / REFERENCE))
.finish()
}
}