use crate::wait_queue::waker::SafeWakerCell;
use std::fmt;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Weak};
use std::task::Waker;
const WAITING: usize = 0;
const NOTIFIED: usize = 1;
const CANCELLED: usize = 2;
#[repr(C)]
pub(crate) struct WaiterState {
state: AtomicUsize,
pub(crate) permits_needed: usize,
waker: SafeWakerCell,
pub(crate) priority: isize,
}
unsafe impl Send for WaiterState {}
unsafe impl Sync for WaiterState {}
pub(crate) struct WaiterHandle {
pub(crate) state: Arc<WaiterState>,
_weak_ref: Weak<WaiterState>,
}
impl WaiterState {
pub(crate) fn new(permits_needed: usize, priority: isize) -> Self {
Self {
state: AtomicUsize::new(WAITING),
permits_needed,
priority,
waker: SafeWakerCell::new(),
}
}
pub(crate) fn cancel(&self) {
if self
.state
.compare_exchange(WAITING, CANCELLED, Ordering::AcqRel, Ordering::Acquire)
.is_ok()
{
unsafe {
self.waker.wake_by_ref_under_lock();
}
return;
}
if self
.state
.compare_exchange(NOTIFIED, CANCELLED, Ordering::AcqRel, Ordering::Acquire)
.is_ok()
{
unsafe {
self.waker.wake_by_ref_under_lock();
}
}
}
pub(crate) fn is_notified(&self) -> bool {
self.state.load(Ordering::Relaxed) == NOTIFIED
}
pub(crate) fn is_cancelled(&self) -> bool {
self.state.load(Ordering::Relaxed) == CANCELLED
}
pub(crate) fn is_waiting(&self) -> bool {
self.state.load(Ordering::Relaxed) == WAITING
}
pub(crate) fn set_waker(&self, waker: Waker) {
unsafe {
self.waker.set_under_lock(waker);
}
}
pub(crate) unsafe fn take_waker_under_lock(&self) -> Option<Waker> {
self.waker.take_under_lock()
}
pub(crate) fn try_notify(&self) -> bool {
self.state
.compare_exchange(WAITING, NOTIFIED, Ordering::AcqRel, Ordering::Acquire)
.is_ok()
}
}
impl WaiterHandle {
pub(crate) fn new(permits_needed: usize, priority: isize) -> Self {
let waiter_state = Arc::new(WaiterState::new(permits_needed, priority));
let weak_ref = Arc::downgrade(&waiter_state);
Self {
state: waiter_state,
_weak_ref: weak_ref,
}
}
}
impl fmt::Debug for WaiterState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let has_waker = unsafe { self.waker.has_waker_under_lock() };
f.debug_struct("WaiterState")
.field("permits_needed", &self.permits_needed)
.field("priority", &self.priority)
.field("state", &self.state.load(Ordering::Relaxed))
.field("has_waker", &has_waker)
.finish()
}
}