update ctrlc Handlers to use Sequence

This commit is contained in:
Andy Gayton 2024-07-02 20:33:12 -04:00
parent c3dee0fef1
commit dbddf3e7fd
3 changed files with 25 additions and 22 deletions

View File

@ -217,12 +217,14 @@ impl PersistentPlugin {
return self.spawn(envs, mutable, ctrlc_handlers); return self.spawn(envs, mutable, ctrlc_handlers);
} }
let guard = ctrlc_handlers.map(|ctrlc_handlers| { let guard = ctrlc_handlers
.map(|ctrlc_handlers| {
let interface = interface.clone(); let interface = interface.clone();
ctrlc_handlers.register(Box::new(move || { ctrlc_handlers.register(Box::new(move || {
let _ = interface.ctrlc(); let _ = interface.ctrlc();
})) }))
}); })
.transpose()?;
mutable.running = Some(RunningPlugin { mutable.running = Some(RunningPlugin {
interface, interface,

View File

@ -517,7 +517,10 @@ impl EngineInterface {
/// Register a closure which will be called when the engine receives a Ctrl-C signal. Returns a /// Register a closure which will be called when the engine receives a Ctrl-C signal. Returns a
/// RAII guard that will keep the closure alive until it is dropped. /// RAII guard that will keep the closure alive until it is dropped.
pub fn register_ctrlc_handler(&self, handler: ctrlc::Handler) -> ctrlc::Guard { pub fn register_ctrlc_handler(
&self,
handler: ctrlc::Handler,
) -> Result<ctrlc::Guard, ShellError> {
self.state.ctrlc_handlers.register(handler) self.state.ctrlc_handlers.register(handler)
} }

View File

@ -1,22 +1,20 @@
use std::fmt::Debug; use std::fmt::Debug;
use std::sync::{ use std::sync::{Arc, Mutex};
atomic::{AtomicU64, Ordering},
Arc, Mutex, use crate::{engine::Sequence, ShellError};
};
pub type Handler = Box<dyn Fn() + Send + Sync>; pub type Handler = Box<dyn Fn() + Send + Sync>;
#[derive(Clone)] #[derive(Clone)]
pub struct Handlers { pub struct Handlers {
handlers: Arc<Mutex<Vec<(u64, Handler)>>>, handlers: Arc<Mutex<Vec<(usize, Handler)>>>,
// we use an u64 so an overflow is impractical next_id: Arc<Sequence>,
next_id: Arc<AtomicU64>,
} }
#[derive(Clone)] #[derive(Clone)]
pub struct Guard { pub struct Guard {
id: u64, id: usize,
handlers: Arc<Mutex<Vec<(u64, Handler)>>>, handlers: Arc<Mutex<Vec<(usize, Handler)>>>,
} }
impl Drop for Guard { impl Drop for Guard {
@ -36,19 +34,19 @@ impl Debug for Guard {
impl Handlers { impl Handlers {
pub fn new() -> Handlers { pub fn new() -> Handlers {
let handlers = Arc::new(Mutex::new(vec![])); let handlers = Arc::new(Mutex::new(vec![]));
let next_id = Arc::new(AtomicU64::new(0)); let next_id = Arc::new(Sequence::default());
Handlers { handlers, next_id } Handlers { handlers, next_id }
} }
pub fn register(&self, handler: Handler) -> Guard { pub fn register(&self, handler: Handler) -> Result<Guard, ShellError> {
let id = self.next_id.fetch_add(1, Ordering::Relaxed); let id = self.next_id.next()?;
if let Ok(mut handlers) = self.handlers.lock() { if let Ok(mut handlers) = self.handlers.lock() {
handlers.push((id, handler)); handlers.push((id, handler));
} }
Guard { Ok(Guard {
id, id,
handlers: Arc::clone(&self.handlers), handlers: Arc::clone(&self.handlers),
} })
} }
pub fn run(&self) { pub fn run(&self) {
@ -69,7 +67,7 @@ impl Default for Handlers {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use std::sync::atomic::AtomicBool; use std::sync::atomic::{AtomicBool, Ordering};
#[test] #[test]
fn test_multiple_handlers() { fn test_multiple_handlers() {