use crush_core::cancel::{AtomicCancellationToken, CancellationToken};
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
pub struct SignalState {
pub token: Arc<dyn CancellationToken>,
pub cancel_flag: Arc<AtomicBool>,
}
pub fn setup_handler() -> Result<SignalState, ctrlc::Error> {
let token: Arc<dyn CancellationToken> = Arc::new(AtomicCancellationToken::new());
let cancel_flag = Arc::new(AtomicBool::new(false));
let handler_token = token.clone();
let handler_flag = cancel_flag.clone();
ctrlc::set_handler(move || {
handler_token.cancel();
handler_flag.store(true, std::sync::atomic::Ordering::SeqCst);
})?;
Ok(SignalState { token, cancel_flag })
}
#[cfg(test)]
mod tests {
use super::*;
use crush_core::cancel::CancellationToken;
use std::sync::atomic::Ordering;
#[test]
fn test_signal_state_token_and_flag_independent() {
let token: Arc<dyn CancellationToken> =
Arc::new(crush_core::cancel::AtomicCancellationToken::new());
let cancel_flag = Arc::new(AtomicBool::new(false));
let state = SignalState {
token: token.clone(),
cancel_flag: cancel_flag.clone(),
};
assert!(!state.token.is_cancelled());
assert!(!state.cancel_flag.load(Ordering::SeqCst));
state.token.cancel();
assert!(state.token.is_cancelled());
assert!(!state.cancel_flag.load(Ordering::SeqCst));
state.cancel_flag.store(true, Ordering::SeqCst);
assert!(state.cancel_flag.load(Ordering::SeqCst));
}
}