use core::{cell::Cell, task::Waker};
use std::{rc::Rc, vec::Vec};
use crate::{cell::LocalCell, queue::Flavor};
pub(super) struct Chan<T> {
flavor: LocalCell<Flavor<T>>,
senders: Cell<usize>,
receiver_alive: Cell<bool>,
recv_waker: LocalCell<Option<Waker>>,
send_wakers: LocalCell<Vec<(u64, Waker)>>,
next_send_id: Cell<u64>,
}
impl<T> Chan<T> {
pub(super) fn bounded(cap: usize) -> Rc<Self> {
Self::new(Flavor::bounded(cap))
}
pub(super) fn unbounded() -> Rc<Self> {
Self::new(Flavor::unbounded())
}
fn new(flavor: Flavor<T>) -> Rc<Self> {
Rc::new(Self {
flavor: LocalCell::new(flavor),
senders: Cell::new(1),
receiver_alive: Cell::new(true),
recv_waker: LocalCell::new(None),
send_wakers: LocalCell::new(Vec::new()),
next_send_id: Cell::new(0),
})
}
pub(super) fn cap(&self) -> Option<usize> {
self.flavor.borrow().cap()
}
pub(super) fn len(&self) -> usize {
self.flavor.borrow().len()
}
pub(super) fn is_empty(&self) -> bool {
self.flavor.borrow().is_empty()
}
pub(super) fn is_full(&self) -> bool {
self.flavor.borrow().is_full()
}
#[inline(always)]
pub(super) fn receiver_alive(&self) -> bool {
self.receiver_alive.get()
}
pub(super) fn senders(&self) -> usize {
self.senders.get()
}
pub(super) fn incr_senders(&self) {
self.senders.set(self.senders.get() + 1);
}
pub(super) fn decr_senders(&self) -> usize {
let n = self.senders.get();
self.senders.set(n - 1);
n
}
pub(super) fn clear_receiver(&self) {
self.receiver_alive.set(false);
}
#[inline(always)]
pub(super) fn wake_receiver(&self) {
if self.recv_waker.borrow().is_none() {
return;
}
let waker = self.recv_waker.borrow_mut().take();
if let Some(waker) = waker {
waker.wake();
}
}
pub(super) fn register_recv_waker(&self, waker: &Waker) {
if !self.receiver_alive.get() {
return;
}
let waker = waker.clone();
let old = self.recv_waker.borrow_mut().replace(waker);
drop(old);
}
pub(super) fn clear_recv_waker(&self) {
let old = self.recv_waker.borrow_mut().take();
drop(old);
}
pub(super) fn add_send_waker(&self, waker: &Waker) -> u64 {
let waker = waker.clone();
let id = self.next_send_id.get();
self.next_send_id.set(id.wrapping_add(1));
self.send_wakers.borrow_mut().push((id, waker));
id
}
pub(super) fn remove_send_waker(&self, id: u64) {
let removed = {
let mut wakers = self.send_wakers.borrow_mut();
wakers
.iter()
.position(|(wid, _)| *wid == id)
.map(|pos| wakers.swap_remove(pos))
};
drop(removed);
}
#[inline(always)]
pub(super) fn wake_senders(&self) {
if self.send_wakers.borrow().is_empty() {
return;
}
let wakers = core::mem::take(&mut *self.send_wakers.borrow_mut());
struct WakeRest(Vec<(u64, Waker)>);
impl Drop for WakeRest {
fn drop(&mut self) {
for (_id, waker) in core::mem::take(&mut self.0) {
waker.wake();
}
}
}
let mut rest = WakeRest(wakers);
while let Some((_id, waker)) = rest.0.pop() {
waker.wake();
}
}
#[inline(always)]
pub(super) fn try_push(&self, item: T) -> Result<(), T> {
self.flavor.borrow_mut().try_push(item)
}
#[inline(always)]
pub(super) fn pop(&self) -> Option<T> {
self.flavor.borrow_mut().pop()
}
pub(super) fn drain(&self) {
struct ContinueOnUnwind<'a, T>(&'a Chan<T>);
impl<T> Drop for ContinueOnUnwind<'_, T> {
fn drop(&mut self) {
self.0.drain();
}
}
let guard = ContinueOnUnwind(self);
while let Some(item) = self.pop() {
drop(item);
}
core::mem::forget(guard);
}
}