use std::sync::{Arc, Weak};
#[repr(transparent)]
pub struct Pusher<I>(pub(crate) Arc<super::Shared<I>>);
use super::StaleErr;
impl<I> Pusher<I> {
#[cfg_attr(feature = "inline-more", inline)]
pub fn push(&self, item: I) -> Result<(), StaleErr> {
let mut inner = self.0.inner.lock();
if inner.npullers == 0 {
Err(StaleErr)
} else {
inner.q.push_back(item);
if let Some((_, n)) = inner.wakers.pop() {
n.wake();
}
self.0.signal.notify_one();
drop(inner);
Ok(())
}
}
#[cfg_attr(feature = "inline-more", inline)]
#[must_use]
pub fn was_empty(&self) -> bool {
let inner = self.0.inner.lock();
inner.q.is_empty()
}
#[must_use]
pub fn weak(&self) -> WeakPusher<I> {
WeakPusher(Arc::downgrade(&self.0))
}
}
impl<I> Clone for Pusher<I> {
fn clone(&self) -> Self {
self.0.inner.lock().npushers += 1;
Self(Arc::clone(&self.0))
}
}
impl<I> Drop for Pusher<I> {
fn drop(&mut self) {
let mut inner = self.0.inner.lock();
inner.npushers -= 1;
if inner.npushers == 0 {
self.0.signal.notify_all();
for waker in inner.wakers.drain(..).map(|(_k, v)| v) {
waker.wake();
}
}
}
}
#[repr(transparent)]
pub struct WeakPusher<I>(pub(crate) Weak<super::Shared<I>>);
impl<I> Clone for WeakPusher<I> {
fn clone(&self) -> Self {
Self(Weak::clone(&self.0))
}
}
impl<I> WeakPusher<I> {
#[must_use]
pub fn upgrade(&self) -> Option<Pusher<I>> {
self.0.upgrade().map_or_else(
|| None,
|strong| {
strong.inner.lock().npushers += 1;
Some(Pusher(Arc::clone(&strong)))
}
)
}
}