use crate::loom::sync::atomic::AtomicPtr;
use crate::runtime::task::{Header, Notified, RawTask};
use std::marker::PhantomData;
use std::ptr;
use std::ptr::NonNull;
use std::sync::atomic::Ordering::SeqCst;
pub(crate) struct AtomicNotified<S: 'static> {
task: AtomicPtr<Header>,
_scheduler: PhantomData<S>,
}
impl<S: 'static> AtomicNotified<S> {
pub(crate) fn empty() -> Self {
Self {
task: AtomicPtr::new(ptr::null_mut()),
_scheduler: PhantomData,
}
}
pub(crate) fn swap(&self, task: Option<Notified<S>>) -> Option<Notified<S>> {
let new = task
.map(|t| t.into_raw().header_ptr().as_ptr())
.unwrap_or_else(ptr::null_mut);
let old = self.task.swap(new, SeqCst);
NonNull::new(old).map(|ptr| unsafe {
Notified::from_raw(RawTask::from_raw(ptr))
})
}
pub(crate) fn take(&self) -> Option<Notified<S>> {
self.swap(None)
}
pub(crate) fn is_some(&self) -> bool {
!self.task.load(SeqCst).is_null()
}
}
unsafe impl<S: Send> Send for AtomicNotified<S> {}
unsafe impl<S: Send> Sync for AtomicNotified<S> {}
impl<S> Drop for AtomicNotified<S> {
fn drop(&mut self) {
let _ = self.take();
}
}