use crate::rand::GlobalRng;
use rand::Rng;
use spin::Mutex;
use std::{fmt, sync::Arc};
pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
let inner = Arc::new(Inner {
queue: Mutex::new(Vec::new()),
});
let sender = Sender {
inner: Arc::clone(&inner),
};
let recver = Receiver { inner };
(sender, recver)
}
pub struct Sender<T> {
inner: Arc<Inner<T>>,
}
pub struct Receiver<T> {
inner: Arc<Inner<T>>,
}
struct Inner<T> {
queue: Mutex<Vec<T>>,
}
impl<T> Clone for Sender<T> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
impl<T> fmt::Debug for SendError<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SendError").finish_non_exhaustive()
}
}
pub struct SendError<T>(pub T);
impl<T> Sender<T> {
pub fn send(&self, value: T) -> Result<(), SendError<T>> {
if let Some(mut queue) = self.inner.queue.try_lock() {
queue.push(value);
return Ok(());
}
Err(SendError(value))
}
}
pub enum TryRecvError {
Empty,
Disconnected,
}
impl<T> Receiver<T> {
pub fn try_recv_random(&self, rng: &GlobalRng) -> Result<T, TryRecvError> {
let mut queue = self.inner.queue.lock();
if !queue.is_empty() {
let idx = rng.with(|rng| rng.gen_range(0..queue.len()));
Ok(queue.swap_remove(idx))
} else if Arc::weak_count(&self.inner) == 0 {
Err(TryRecvError::Disconnected)
} else {
Err(TryRecvError::Empty)
}
}
}