use std::{
sync::{Arc, atomic::Ordering},
task::Poll,
};
use crate::{
Counts, State, Weak,
lock::*,
producer::{Mut, Producer, Ref},
waiter::*,
};
#[derive(Debug)]
pub struct Consumer<T> {
pub(crate) state: Lock<State<T>>,
pub(crate) counts: Arc<Counts>,
}
impl<T> Consumer<T> {
pub fn poll<F, R>(&self, waiter: &Waiter, mut f: F) -> Poll<Result<R, Ref<'_, T>>>
where
F: FnMut(&Ref<'_, T>) -> Poll<R>,
{
let state = self.state.lock();
let consumer_state = Ref { state };
if let Poll::Ready(res) = f(&consumer_state) {
return Poll::Ready(Ok(res));
}
if consumer_state.state.closed {
return Poll::Ready(Err(consumer_state));
}
let mut state = consumer_state.state;
waiter.register(&mut state.waiters_value);
Poll::Pending
}
pub fn write(&self) -> Result<Mut<'_, T>, Ref<'_, T>> {
let state = self.state.lock();
if state.closed {
Err(Ref { state })
} else {
Ok(Mut::new(state))
}
}
pub fn poll_closed(&self, waiter: &Waiter) -> Poll<()> {
let mut state = self.state.lock();
if state.closed {
return Poll::Ready(());
}
waiter.register(&mut state.waiters_closed);
Poll::Pending
}
pub async fn wait<F, R>(&self, mut f: F) -> Result<R, Ref<'_, T>>
where
F: FnMut(&Ref<'_, T>) -> Poll<R> + Unpin,
R: Unpin,
{
crate::wait(move |waiter| self.poll(waiter, &mut f)).await
}
pub async fn closed(&self) {
crate::wait(move |waiter| self.poll_closed(waiter)).await
}
pub fn produce(&self) -> Option<Producer<T>> {
self.counts.producers.fetch_add(1, Ordering::Relaxed);
{
let state = self.state.lock();
if state.closed {
self.counts.producers.fetch_sub(1, Ordering::Relaxed);
return None;
}
}
Some(Producer {
state: self.state.clone(),
counts: self.counts.clone(),
})
}
pub fn read(&self) -> Ref<'_, T> {
Ref {
state: self.state.lock(),
}
}
pub fn same_channel(&self, other: &Self) -> bool {
self.state.is_clone(&other.state)
}
pub fn weak(&self) -> Weak<T> {
Weak {
state: self.state.clone(),
counts: self.counts.clone(),
}
}
}
impl<T> Drop for Consumer<T> {
fn drop(&mut self) {
let prev = self.counts.consumers.fetch_sub(1, Ordering::AcqRel);
if prev > 1 {
return;
}
let mut waiters = {
let mut state = self.state.lock();
state.waiters_consumer.take()
};
waiters.wake();
}
}
impl<T> Clone for Consumer<T> {
fn clone(&self) -> Self {
self.counts.consumers.fetch_add(1, Ordering::Relaxed);
Self {
state: self.state.clone(),
counts: self.counts.clone(),
}
}
}