use core::{ptr, sync::atomic::Ordering};
use super::CoroutineHeader;
use crate::runtime::delivery::epoch::EpochMpscQueue;
#[derive(Clone, Copy)]
pub(super) enum InboxKind {
Ready,
}
pub(super) struct IntrusiveInbox {
publication: EpochMpscQueue<CoroutineHeader>,
kind: InboxKind,
}
impl IntrusiveInbox {
pub(super) const fn new(kind: InboxKind) -> Self {
Self {
publication: EpochMpscQueue::new(),
kind,
}
}
pub(super) fn is_empty(&self) -> bool {
self.publication.is_empty()
}
pub(super) unsafe fn push(&self, header: *mut CoroutineHeader) {
let next = unsafe {
(*header).next(self.kind)
};
unsafe {
self.publication.publish(header, next);
}
}
pub(super) unsafe fn take_fifo(&self) -> *mut CoroutineHeader {
let stack = unsafe {
self.publication.take_graced_stack()
};
unsafe {
reverse(stack, self.kind)
}
}
pub(super) unsafe fn take_next(
header: *mut CoroutineHeader,
kind: InboxKind,
) -> *mut CoroutineHeader {
unsafe {
(*header)
.next(kind)
.swap(ptr::null_mut(), Ordering::Relaxed)
}
}
}
unsafe fn reverse(mut cursor: *mut CoroutineHeader, kind: InboxKind) -> *mut CoroutineHeader {
let mut reversed = ptr::null_mut();
while !cursor.is_null() {
let next = unsafe {
(*cursor).next(kind).load(Ordering::Relaxed)
};
unsafe {
(*cursor).next(kind).store(reversed, Ordering::Relaxed);
}
reversed = cursor;
cursor = next;
}
reversed
}