use crate::*;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{self, Receiver, Sender};
use std::sync::Arc;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub(crate) struct MessageChannelId(usize);
impl MessageChannelId {
pub(crate) fn from_sender(msg_send: &MessageSender) -> Self {
Self(msg_send.msg_type_id.as_ref() as *const _ as usize)
}
pub(crate) fn from_receiver(msg_recv: &MessageReceiver) -> Self {
Self(msg_recv.msg_type_id.as_ref() as *const _ as usize)
}
}
pub(crate) struct MessageSender {
msg_type_id: Arc<MessageTypeId>,
send: Sender<Arc<dyn Message>>,
is_active: Arc<AtomicBool>,
}
impl MessageSender {
pub(crate) fn channel_id(&self) -> MessageChannelId {
MessageChannelId::from_sender(self)
}
pub(crate) fn message_type_id(&self) -> MessageTypeId {
*self.msg_type_id
}
pub(crate) fn is_active(&self) -> bool {
self.is_active.load(Ordering::SeqCst)
}
#[allow(dead_code)]
pub(crate) fn set_active(&self, is_active: bool) {
self.is_active.store(is_active, Ordering::SeqCst);
}
pub(crate) fn send(&self, msg: Arc<dyn Message>) -> Result<(), MessageChannelError> {
if msg.type_id() == self.message_type_id() {
return self
.send
.send(msg)
.map_err(|_| MessageChannelError::MessageNotSent);
}
Err(MessageChannelError::WrongMessageType)
}
}
pub(crate) struct MessageReceiver {
msg_type_id: Arc<MessageTypeId>,
recv: Receiver<Arc<dyn Message>>,
is_active: Arc<AtomicBool>,
}
impl MessageReceiver {
pub(crate) fn channel_id(&self) -> MessageChannelId {
MessageChannelId::from_receiver(self)
}
pub(crate) fn message_type_id(&self) -> MessageTypeId {
*self.msg_type_id
}
pub(crate) fn is_active(&self) -> bool {
self.is_active.load(Ordering::SeqCst)
}
pub(crate) fn set_active(&self, is_active: bool) {
self.is_active.store(is_active, Ordering::SeqCst);
}
pub(crate) fn recv(&self) -> Option<Arc<dyn Message>> {
self.recv.try_recv().ok()
}
}
pub(crate) fn message_channel_new(msg_type_id: MessageTypeId) -> (MessageSender, MessageReceiver) {
let msg_type_id = Arc::new(msg_type_id);
let (send, recv) = mpsc::channel();
let is_active = Arc::new(AtomicBool::new(true));
let msg_send = MessageSender {
msg_type_id: Arc::clone(&msg_type_id),
send,
is_active: Arc::clone(&is_active),
};
let msg_recv = MessageReceiver {
msg_type_id: Arc::clone(&msg_type_id),
recv,
is_active,
};
(msg_send, msg_recv)
}
#[derive(Debug)]
pub enum MessageChannelError {
WrongMessageType,
MessageNotSent,
}