use std::sync::Arc;
#[cfg(unix)]
use {mio::unix::pipe, parking_lot::Mutex, std::io::Write};
#[cfg(windows)]
use {
crate::win,
std::sync::atomic::{AtomicU32, Ordering},
windows_sys::Win32::{Foundation::HANDLE, System::Threading::SetEvent}
};
use crate::err::Error;
#[derive(Clone)]
pub(crate) struct CmdSignal {
#[cfg(unix)]
pub(crate) ctl_tx: Arc<Mutex<pipe::Sender>>,
#[cfg(windows)]
pub(crate) cmdreq: Arc<AtomicU32>,
#[cfg(windows)]
pub(crate) hev_wakeup: HANDLE
}
impl CmdSignal {
pub(crate) fn kill<E>(&self) -> Result<(), Error<E>> {
#[cfg(unix)]
{
let buf = "t";
self.ctl_tx.lock().write_all(buf.as_bytes()).map_err(|e| {
Error::Internal(format!(
"Unable to send termination signal to receiver thread; {}",
e
))
})?;
}
#[cfg(windows)]
{
self
.cmdreq
.fetch_or(win::CmdFlags::KILL.bits(), Ordering::SeqCst);
unsafe {
if SetEvent(self.hev_wakeup) == 0 {
Err(Error::Internal(format!(
"Unable to send termination signal to receiver thread"
)))?;
}
}
}
Ok(())
}
#[cfg(feature = "inspect")]
pub(crate) fn inspect(&self) {
#[cfg(unix)]
{
let buf = "i";
if let Err(e) = self.ctl_tx.lock().write_all(buf.as_bytes()) {
eprintln!("Unable to send inspect signal to receiver thread; {}", e);
}
}
#[cfg(windows)]
{
self
.cmdreq
.fetch_or(win::CmdFlags::INSPECT.bits(), Ordering::SeqCst);
unsafe {
if SetEvent(self.hev_wakeup) == 0 {
eprintln!("Unable to send inspect signal to receiver thread");
}
}
}
}
#[cfg(feature = "idle")]
pub(crate) fn idle(&self) {
#[cfg(unix)]
{
let buf = "d";
if let Err(e) = self.ctl_tx.lock().write_all(buf.as_bytes()) {
eprintln!("Unable to send idle command to receiver thread; {}", e);
}
}
#[cfg(windows)]
{
self
.cmdreq
.fetch_or(win::CmdFlags::IDLE.bits(), Ordering::SeqCst);
unsafe {
if SetEvent(self.hev_wakeup) == 0 {
eprintln!("Unable to send idle signal to receiver thread");
}
}
}
}
#[allow(dead_code)]
pub(crate) fn channel(&self) {
#[cfg(unix)]
{
let buf = "c";
if let Err(e) = self.ctl_tx.lock().write_all(buf.as_bytes()) {
eprintln!("Unable to send channel command to receiver thread; {}", e);
}
}
#[cfg(windows)]
{
self
.cmdreq
.fetch_or(win::CmdFlags::CHANNEL.bits(), Ordering::SeqCst);
unsafe {
if SetEvent(self.hev_wakeup) == 0 {
eprintln!("Unable to send channel signal to receiver thread");
}
}
}
}
}