use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
pub struct Shutdown<'w>(pub(crate) &'w AtomicBool);
impl Shutdown<'_> {
#[inline(always)]
pub fn is_shutdown(&self) -> bool {
self.0.load(Ordering::Relaxed)
}
pub fn trigger(&self) {
self.0.store(true, Ordering::Relaxed);
}
}
impl std::fmt::Debug for Shutdown<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("Shutdown")
.field(&self.is_shutdown())
.finish()
}
}
pub struct ShutdownHandle {
flag: Arc<AtomicBool>,
}
impl ShutdownHandle {
pub(crate) fn new(flag: Arc<AtomicBool>) -> Self {
Self { flag }
}
pub fn is_shutdown(&self) -> bool {
self.flag.load(Ordering::Relaxed)
}
pub fn shutdown(&self) {
self.flag.store(true, Ordering::Relaxed);
}
#[cfg(feature = "signals")]
pub fn enable_signals(&self) -> std::io::Result<()> {
signal_hook::flag::register(signal_hook::consts::SIGINT, Arc::clone(&self.flag))?;
signal_hook::flag::register(signal_hook::consts::SIGTERM, Arc::clone(&self.flag))?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn handle_not_shutdown_by_default() {
let world = crate::WorldBuilder::new().build();
let handle = world.shutdown_handle();
assert!(!handle.is_shutdown());
}
#[test]
fn shutdown_param_triggers() {
let world = crate::WorldBuilder::new().build();
let handle = world.shutdown_handle();
let shutdown = Shutdown(world.shutdown_flag());
assert!(!handle.is_shutdown());
shutdown.trigger();
assert!(handle.is_shutdown());
}
#[test]
fn handle_can_trigger_shutdown() {
let world = crate::WorldBuilder::new().build();
let handle = world.shutdown_handle();
assert!(!handle.is_shutdown());
handle.shutdown();
assert!(handle.is_shutdown());
}
#[test]
fn shutdown_in_handler() {
use crate::{Handler, IntoHandler};
fn trigger_shutdown(shutdown: Shutdown, _event: ()) {
shutdown.trigger();
}
let mut world = crate::WorldBuilder::new().build();
let handle = world.shutdown_handle();
let mut handler = trigger_shutdown.into_handler(world.registry());
assert!(!handle.is_shutdown());
handler.run(&mut world, ());
assert!(handle.is_shutdown());
}
}