use std::marker::PhantomPinned;
use std::task::Context;
use crate::task::waker_as_task_ptr;
use crate::task::ITask;
use crate::{EventId, Reactor, Runtime};
#[derive(Debug)]
pub struct EventNode {
next: *mut EventNode,
prev: *mut EventNode,
task_ptr: Option<*const dyn ITask>,
_pin: PhantomPinned,
}
impl EventNode {
pub fn new() -> Self {
EventNode {
next: std::ptr::null_mut(),
prev: std::ptr::null_mut(),
task_ptr: None,
_pin: PhantomPinned,
}
}
pub unsafe fn on_pin(&mut self, ctx: &Context) -> EventId {
self.task_ptr = Some(waker_as_task_ptr(&ctx.waker()));
self.get_event_id()
}
pub fn is_awoken_for<ReactorT: Reactor>(&self, rt: &Runtime<ReactorT>) -> bool {
rt.is_awoken_for(self.get_event_id())
}
pub fn on_cancel(&mut self) -> Option<EventId> {
if self.is_self_in_list() {
unsafe { self.remove_self_from_list() }
None
} else {
Some(self.get_event_id())
}
}
pub fn get_event_id(&self) -> EventId {
EventId(self as *const Self as *const ())
}
fn is_self_in_list(&self) -> bool {
self.prev != std::ptr::null_mut()
}
unsafe fn remove_self_from_list(&mut self) {
debug_assert!(self.is_self_in_list());
(*(self.prev)).next = self.next;
if self.next != std::ptr::null_mut() {
(*(self.next)).prev = self.prev;
}
self.next = std::ptr::null_mut();
self.prev = std::ptr::null_mut();
}
pub(crate) fn get_itask_ptr(&self) -> *const dyn ITask {
self.task_ptr.unwrap()
}
pub(crate) unsafe fn push_back(&mut self, event_id: EventId) {
let mut cur = self;
while cur.next != std::ptr::null_mut() {
cur = &mut *(cur.next);
}
let node = event_id.0 as *mut EventNode;
(*node).prev = cur;
(*cur).next = node;
}
pub(crate) unsafe fn find_unfrozen(&mut self) -> Option<EventId> {
let mut cur = self;
while cur.next != std::ptr::null_mut() {
cur = &mut *(cur.next);
if !(*(cur.task_ptr.unwrap())).is_frozen() {
cur.remove_self_from_list();
return Some(cur.get_event_id());
}
}
None
}
}
impl Drop for EventNode {
fn drop(&mut self) {
debug_assert!(
!self.is_self_in_list(),
"aiur/EventNode: {:?} is dropped while being in frozen list",
self.get_event_id(),
);
}
}