use std::collections::VecDeque;
use std::future::Future;
use std::pin::Pin;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
use std::task::{Context, Poll};
pub struct MkAsyncChannel<T> {
inner: Arc<ChannelInner<T>>,
}
struct ChannelInner<T> {
queue: Mutex<VecDeque<T>>,
capacity: usize,
len: AtomicUsize,
closed: AtomicBool,
}
impl<T> MkAsyncChannel<T> {
pub fn bounded(capacity: usize) -> Self {
Self {
inner: Arc::new(ChannelInner {
queue: Mutex::new(VecDeque::with_capacity(capacity)),
capacity,
len: AtomicUsize::new(0),
closed: AtomicBool::new(false),
}),
}
}
pub fn split(self) -> (MkAsyncSender<T>, MkAsyncReceiver<T>) {
(
MkAsyncSender { inner: Arc::clone(&self.inner) },
MkAsyncReceiver { inner: self.inner },
)
}
pub fn capacity(&self) -> usize {
self.inner.capacity
}
pub fn len(&self) -> usize {
self.inner.len.load(Ordering::Relaxed)
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
pub struct MkAsyncSender<T> {
inner: Arc<ChannelInner<T>>,
}
impl<T> MkAsyncSender<T> {
pub async fn send(&self, value: T) -> Result<(), SendError<T>> {
if self.inner.closed.load(Ordering::Acquire) {
return Err(SendError::Closed(value));
}
loop {
let len = self.inner.len.load(Ordering::Acquire);
if len < self.inner.capacity {
let mut queue = self.inner.queue.lock().unwrap();
if queue.len() < self.inner.capacity {
queue.push_back(value);
self.inner.len.fetch_add(1, Ordering::Release);
return Ok(());
}
}
YieldOnce::new().await;
if self.inner.closed.load(Ordering::Acquire) {
return Err(SendError::Closed(value));
}
}
}
pub fn try_send(&self, value: T) -> Result<(), SendError<T>> {
if self.inner.closed.load(Ordering::Acquire) {
return Err(SendError::Closed(value));
}
let mut queue = self.inner.queue.lock().unwrap();
if queue.len() < self.inner.capacity {
queue.push_back(value);
self.inner.len.fetch_add(1, Ordering::Release);
Ok(())
} else {
Err(SendError::Full(value))
}
}
pub fn close(&self) {
self.inner.closed.store(true, Ordering::Release);
}
}
impl<T> Clone for MkAsyncSender<T> {
fn clone(&self) -> Self {
Self { inner: Arc::clone(&self.inner) }
}
}
pub struct MkAsyncReceiver<T> {
inner: Arc<ChannelInner<T>>,
}
impl<T> MkAsyncReceiver<T> {
pub async fn recv(&self) -> Option<T> {
loop {
if let Some(value) = self.try_recv() {
return Some(value);
}
if self.inner.closed.load(Ordering::Acquire) && self.inner.len.load(Ordering::Acquire) == 0 {
return None;
}
YieldOnce::new().await;
}
}
pub fn try_recv(&self) -> Option<T> {
let mut queue = self.inner.queue.lock().unwrap();
if let Some(value) = queue.pop_front() {
self.inner.len.fetch_sub(1, Ordering::Release);
Some(value)
} else {
None
}
}
pub fn is_closed(&self) -> bool {
self.inner.closed.load(Ordering::Acquire)
}
}
#[derive(Debug)]
pub enum SendError<T> {
Full(T),
Closed(T),
}
impl<T> SendError<T> {
pub fn into_inner(self) -> T {
match self {
SendError::Full(v) | SendError::Closed(v) => v,
}
}
}
struct YieldOnce(bool);
impl YieldOnce {
fn new() -> Self {
Self(false)
}
}
impl Future for YieldOnce {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if self.0 {
Poll::Ready(())
} else {
self.0 = true;
cx.waker().wake_by_ref();
Poll::Pending
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_channel_sync() {
let channel: MkAsyncChannel<u32> = MkAsyncChannel::bounded(3);
let (tx, rx) = channel.split();
tx.try_send(1).unwrap();
tx.try_send(2).unwrap();
tx.try_send(3).unwrap();
assert!(tx.try_send(4).is_err());
assert_eq!(rx.try_recv(), Some(1));
assert_eq!(rx.try_recv(), Some(2));
assert_eq!(rx.try_recv(), Some(3));
assert_eq!(rx.try_recv(), None);
}
}