use std::{
ops::{Deref, DerefMut},
sync::{Arc, atomic::Ordering},
task::Poll,
};
use crate::{Counts, State, consumer::Consumer, lock::*, waiter::*, weak::Weak};
#[derive(Debug)]
pub struct Producer<T> {
pub(crate) state: Lock<State<T>>,
pub(crate) counts: Arc<Counts>,
}
impl<T: Default> Default for Producer<T> {
fn default() -> Self {
Self {
state: Lock::new(State::default()),
counts: Arc::new(Counts::default()),
}
}
}
impl<T> Producer<T> {
pub fn new(value: T) -> Self {
Self {
state: Lock::new(State::new(value)),
counts: Arc::new(Counts::default()),
}
}
pub fn consume(&self) -> Consumer<T> {
let prev = self.counts.consumers.fetch_add(1, Ordering::AcqRel);
if prev == 0 {
let mut waiters = self.state.lock().waiters.take();
waiters.wake();
}
Consumer {
state: self.state.clone(),
counts: self.counts.clone(),
}
}
pub fn close(&self) -> Result<(), Ref<'_, T>> {
self.write()?.close();
Ok(())
}
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<F, R>(&self, waiter: &Waiter, mut f: F) -> Poll<Result<R, Ref<'_, T>>>
where
F: FnMut(&mut Mut<'_, T>) -> Poll<R>,
{
let mut state = self.write()?;
if let Poll::Ready(res) = f(&mut state) {
return Poll::Ready(Ok(res));
}
let inner = state.state.as_mut().unwrap();
let waiters = if state.modified {
Some(inner.waiters.take())
} else {
None
};
waiter.register(&mut inner.waiters);
state.modified = false;
drop(state);
if let Some(mut waiters) = waiters {
waiters.wake();
}
Poll::Pending
}
pub async fn wait<F, R>(&self, mut f: F) -> Result<R, Ref<'_, T>>
where
F: FnMut(&mut Mut<'_, 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
}
fn poll_closed(&self, waiter: &Waiter) -> Poll<()> {
let mut state = self.state.lock();
if state.closed {
return Poll::Ready(());
}
waiter.register(&mut state.waiters);
Poll::Pending
}
pub async fn unused(&self) -> Result<(), Ref<'_, T>> {
match crate::wait(move |waiter| self.poll_unused(waiter)).await {
Some(()) => Ok(()),
None => Err(self.read()),
}
}
fn poll_unused(&self, waiter: &Waiter) -> Poll<Option<()>> {
let mut state = self.state.lock();
if state.closed {
return Poll::Ready(None);
}
if self.counts.consumers.load(Ordering::Relaxed) == 0 {
return Poll::Ready(Some(()));
}
waiter.register(&mut state.waiters);
if self.counts.consumers.load(Ordering::Relaxed) == 0 {
return Poll::Ready(Some(()));
}
Poll::Pending
}
pub async fn used(&self) -> Result<(), Ref<'_, T>> {
match crate::wait(move |waiter| self.poll_used(waiter)).await {
Some(()) => Ok(()),
None => Err(self.read()),
}
}
fn poll_used(&self, waiter: &Waiter) -> Poll<Option<()>> {
let mut state = self.state.lock();
if state.closed {
return Poll::Ready(None);
}
if self.counts.consumers.load(Ordering::Relaxed) > 0 {
return Poll::Ready(Some(()));
}
waiter.register(&mut state.waiters);
if self.counts.consumers.load(Ordering::Relaxed) > 0 {
return Poll::Ready(Some(()));
}
Poll::Pending
}
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> Clone for Producer<T> {
fn clone(&self) -> Self {
self.counts.producers.fetch_add(1, Ordering::Relaxed);
Self {
state: self.state.clone(),
counts: self.counts.clone(),
}
}
}
impl<T> Drop for Producer<T> {
fn drop(&mut self) {
let prev = self.counts.producers.fetch_sub(1, Ordering::AcqRel);
if prev > 1 {
return;
}
let mut waiters = {
let mut state = self.state.lock();
if state.closed {
return;
}
state.closed = true;
state.waiters.take()
};
waiters.wake();
}
}
#[derive(Debug)]
pub struct Mut<'a, T> {
pub(crate) state: Option<LockGuard<'a, State<T>>>,
pub(crate) modified: bool,
}
impl<'a, T> Mut<'a, T> {
pub(crate) fn new(state: LockGuard<'a, State<T>>) -> Self {
Self {
state: Some(state),
modified: false,
}
}
pub fn close(mut self) {
let state = self.state.as_mut().unwrap();
state.closed = true;
self.modified = true;
}
}
impl<T> Deref for Mut<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.state.as_ref().unwrap().value
}
}
impl<T> DerefMut for Mut<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.modified = true;
&mut self.state.as_mut().unwrap().value
}
}
impl<T> Drop for Mut<'_, T> {
fn drop(&mut self) {
let mut state = self.state.take().unwrap();
if !self.modified {
return;
}
let mut waiters = state.waiters.take();
drop(state);
waiters.wake();
}
}
pub struct Ref<'a, T> {
pub(crate) state: LockGuard<'a, State<T>>,
}
impl<T> Ref<'_, T> {
pub fn is_closed(&self) -> bool {
self.state.closed
}
}
impl<T> Deref for Ref<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.state.value
}
}