use std::thread::{self, ThreadId};
use super::dispatch::DispatchMessage;
#[derive(Debug)]
pub struct DispatchSender<T> {
channel: DispatchChannel<T>,
}
pub type EventSender<T> = DispatchSender<T>;
impl<T> DispatchSender<T> {
#[must_use]
pub fn new(sender: tokio::sync::mpsc::UnboundedSender<DispatchMessage<T>>) -> Self {
Self {
channel: DispatchChannel::Dispatch {
sender,
owner: thread::current().id(),
},
}
}
pub fn send(
&self,
message: T,
) -> Result<(), tokio::sync::mpsc::error::SendError<DispatchMessage<T>>> {
match &self.channel {
DispatchChannel::Plain(sender) => sender
.send(message)
.map_err(|e| tokio::sync::mpsc::error::SendError(e.0.into())),
DispatchChannel::Dispatch { sender, owner } => {
sender.send(DispatchMessage::new(message, *owner))
}
}
}
#[must_use]
pub fn is_closed(&self) -> bool {
match &self.channel {
DispatchChannel::Plain(sender) => sender.is_closed(),
DispatchChannel::Dispatch { sender, .. } => sender.is_closed(),
}
}
#[must_use]
pub fn same_channel(&self, other: &Self) -> bool {
match (&self.channel, &other.channel) {
(DispatchChannel::Plain(left), DispatchChannel::Plain(right)) => {
left.same_channel(right)
}
(
DispatchChannel::Dispatch { sender: left, .. },
DispatchChannel::Dispatch { sender: right, .. },
) => left.same_channel(right),
_ => false,
}
}
}
impl<T> Clone for DispatchSender<T> {
fn clone(&self) -> Self {
let channel = match &self.channel {
DispatchChannel::Plain(sender) => DispatchChannel::Plain(sender.clone()),
DispatchChannel::Dispatch { sender, owner } => DispatchChannel::Dispatch {
sender: sender.clone(),
owner: *owner,
},
};
Self { channel }
}
}
impl<T> From<tokio::sync::mpsc::UnboundedSender<T>> for DispatchSender<T> {
fn from(sender: tokio::sync::mpsc::UnboundedSender<T>) -> Self {
Self {
channel: DispatchChannel::Plain(sender),
}
}
}
#[derive(Debug)]
enum DispatchChannel<T> {
Plain(tokio::sync::mpsc::UnboundedSender<T>),
Dispatch {
sender: tokio::sync::mpsc::UnboundedSender<DispatchMessage<T>>,
owner: ThreadId,
},
}