use core::{
cell::UnsafeCell,
marker::PhantomPinned,
ptr,
sync::atomic::{AtomicBool, AtomicPtr, Ordering},
};
use super::{InboxKind, InboxMessage};
#[derive(Debug)]
pub struct InboxNode {
kind: InboxKind,
next: AtomicPtr<Self>,
queued: AtomicBool,
message: UnsafeCell<InboxMessage>,
_pin: PhantomPinned,
}
impl InboxNode {
pub const fn new(kind: InboxKind) -> Self {
Self {
kind,
next: AtomicPtr::new(ptr::null_mut()),
queued: AtomicBool::new(false),
message: UnsafeCell::new(InboxMessage::EMPTY),
_pin: PhantomPinned,
}
}
pub const fn kind(&self) -> InboxKind {
self.kind
}
pub(super) fn reserve(&self, message: InboxMessage) -> bool {
if self
.queued
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
.is_err()
{
return false;
}
unsafe {
*self.message.get() = message;
}
true
}
pub(super) const fn next(&self) -> &AtomicPtr<Self> {
&self.next
}
pub(super) unsafe fn take_next(&self) -> *mut Self {
self.next.swap(ptr::null_mut(), Ordering::Relaxed)
}
pub(super) unsafe fn take_message(&self) -> InboxMessage {
let message = unsafe {
*self.message.get()
};
self.queued.store(false, Ordering::Release);
message
}
}
unsafe impl Send for InboxNode {}
unsafe impl Sync for InboxNode {}