use crossbeam_channel::Sender;
use mio::Waker;
use std::io;
use std::io::ErrorKind;
use std::sync::Arc;
use crate::wire;
pub enum ControlMessage {
Command(Box<wire::Control>),
Shutdown,
}
#[derive(Clone)]
pub struct Controller {
sender: Sender<ControlMessage>,
waker: Arc<Waker>,
}
impl Controller {
pub fn new(sender: Sender<ControlMessage>, waker: Arc<Waker>) -> Self {
Self { sender, waker }
}
pub fn wake(&self) -> io::Result<()> {
log::trace!(target: "reactor::controller", "Wakening the reactor");
self.waker.wake()
}
pub fn cmd(&self, command: wire::Control) -> io::Result<()> {
log::trace!(target: "reactor::controller", "Sending command {command:?} to the reactor");
self.sender
.send(ControlMessage::Command(Box::new(command)))
.map_err(|_| ErrorKind::BrokenPipe)?;
self.wake()
}
pub fn shutdown(self) -> Result<(), Self> {
log::info!(target: "reactor::controller", "Initiating reactor shutdown...");
let res1 = self.sender.send(ControlMessage::Shutdown);
let res2 = self.wake();
res1.or(res2).map_err(|_| self)
}
}