use std::sync::atomic::{AtomicBool, Ordering::Relaxed};
use std::sync::{Arc, Mutex, Weak};
use std::thread;
use signal_hook::consts::SIGINT;
use signal_hook::iterator::Signals;
struct Suppressor {
new_signal: AtomicBool,
}
impl Suppressor {
fn signal_received(&self) {
self.new_signal.store(true, Relaxed);
}
}
pub struct SuppressorHandle {
state: Arc<Suppressor>,
}
impl SuppressorHandle {
fn new() -> SuppressorHandle {
SuppressorHandle {
state: Arc::new(Suppressor {
new_signal: AtomicBool::new(false),
}),
}
}
pub fn was_signaled(&self) -> bool {
self.state.new_signal.swap(false, Relaxed)
}
pub fn release(self) -> bool {
self.was_signaled()
}
}
type Suppressors = Arc<Mutex<Vec<Weak<Suppressor>>>>;
pub struct Manager {
suppressors: Suppressors,
}
fn enable_suppression(suppressors: Suppressors) {
thread::spawn(move || {
let mut signals = Signals::new([SIGINT])
.map_err(|err| format!("Couldn't register interrupt handler: {err}"))
.unwrap();
for _signal in signals.forever() {
let mut suppressors = suppressors.lock().unwrap();
if suppressors.is_empty() {
std::process::exit(0)
} else {
let mut remaining: Vec<Weak<Suppressor>> = vec![];
for weak in suppressors.iter() {
if let Some(s) = weak.upgrade() {
s.signal_received();
remaining.push(weak.clone());
}
}
*suppressors = remaining;
}
}
});
}
impl Manager {
pub fn setup() -> Manager {
let suppressors = Arc::new(Mutex::new(Vec::<Weak<Suppressor>>::new()));
enable_suppression(suppressors.clone());
Manager { suppressors }
}
pub fn suppress(&mut self) -> SuppressorHandle {
let handle = SuppressorHandle::new();
let suppressor = handle.state.clone();
self.suppressors
.lock()
.unwrap()
.push(Arc::downgrade(&suppressor));
handle
}
}