use std::collections::VecDeque;
use std::fmt::{self, Debug, Display};
use std::sync::{Arc, Mutex};
#[derive(Debug)]
pub enum ChannelError {
Poisoned,
}
impl Display for ChannelError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Channel mutex is poisoned")
}
}
#[derive(Debug)]
pub struct Channel<T: Debug + Send + Sync> {
queue: Mutex<VecDeque<T>>,
}
impl<T: Debug + Send + Sync> Channel<T> {
#[must_use]
pub fn create() -> (Sender<T>, Receiver<T>) {
let channel = Arc::new(Self {
queue: Mutex::new(VecDeque::new()),
});
let sender = Sender {
channel: Arc::clone(&channel),
};
let receiver = Receiver {
channel: Arc::clone(&channel),
};
(sender, receiver)
}
}
#[derive(Debug)]
pub struct Sender<T: Debug + Send + Sync> {
channel: Arc<Channel<T>>,
}
impl<T: Debug + Send + Sync> Clone for Sender<T> {
fn clone(&self) -> Self {
Self {
channel: self.channel.clone(),
}
}
}
impl<T: Debug + Send + Sync> Sender<T> {
pub fn send(&self, message: T) -> Result<(), ChannelError> {
let mut queue = self
.channel
.queue
.lock()
.map_err(|_| ChannelError::Poisoned)?;
queue.push_back(message);
Ok(())
}
}
#[derive(Debug)]
pub struct Receiver<T: Debug + Send + Sync> {
channel: Arc<Channel<T>>,
}
impl<T: Debug + Send + Sync> Receiver<T> {
pub fn try_recv(&self) -> Option<T> {
let mut queue = self.channel.queue.lock().unwrap();
queue.pop_front()
}
pub fn recv(&self) -> Result<T, ChannelError> {
let mut queue = self
.channel
.queue
.lock()
.map_err(|_| ChannelError::Poisoned)?;
queue.pop_front().ok_or(ChannelError::Poisoned)
}
}