diff --git a/src/bridge/mod.rs b/src/bridge/mod.rs index e40eecd..8242273 100644 --- a/src/bridge/mod.rs +++ b/src/bridge/mod.rs @@ -6,7 +6,6 @@ mod ui_commands; use std::path::Path; use std::process::Stdio; -use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use log::{error, info, warn}; @@ -17,6 +16,7 @@ use tokio::runtime::Runtime; use tokio::sync::mpsc::UnboundedReceiver; use crate::channel_utils::*; +use crate::running_tracker::*; use crate::settings::*; use crate::{cmd_line::CmdLineSettings, error_handling::ResultPanicExplanation}; pub use events::*; @@ -158,7 +158,6 @@ async fn start_neovim_runtime( ui_command_sender: LoggingTx, ui_command_receiver: UnboundedReceiver, redraw_event_sender: LoggingTx, - running: Arc, ) { let handler = NeovimHandler::new(ui_command_sender.clone(), redraw_event_sender.clone()); let (nvim, io_handler) = match connection_mode() { @@ -172,7 +171,6 @@ async fn start_neovim_runtime( std::process::exit(-1); } - let close_watcher_running = running.clone(); tokio::spawn(async move { info!("Close watcher started"); match io_handler.await { @@ -184,7 +182,7 @@ async fn start_neovim_runtime( } Ok(Ok(())) => {} }; - close_watcher_running.store(false, Ordering::Relaxed); + RUNNING_TRACKER.quit("neovim processed failed"); }); match nvim.command_output("echo has('nvim-0.4')").await.as_deref() { @@ -284,7 +282,7 @@ async fn start_neovim_runtime( let nvim = Arc::new(nvim); - start_ui_command_handler(running.clone(), ui_command_receiver, nvim.clone()); + start_ui_command_handler(ui_command_receiver, nvim.clone()); SETTINGS.read_initial_values(&nvim).await; SETTINGS.setup_changed_listeners(&nvim).await; } @@ -297,14 +295,12 @@ pub fn start_bridge( ui_command_sender: LoggingTx, ui_command_receiver: UnboundedReceiver, redraw_event_sender: LoggingTx, - running: Arc, ) -> Bridge { let runtime = Runtime::new().unwrap(); runtime.spawn(start_neovim_runtime( ui_command_sender, ui_command_receiver, redraw_event_sender, - running, )); Bridge { _runtime: runtime } } diff --git a/src/bridge/ui_commands.rs b/src/bridge/ui_commands.rs index 05d7a4b..71bc9f1 100644 --- a/src/bridge/ui_commands.rs +++ b/src/bridge/ui_commands.rs @@ -18,6 +18,7 @@ use tokio::sync::mpsc::{ }; use crate::bridge::TxWrapper; +use crate::running_tracker::RUNNING_TRACKER; #[cfg(windows)] use crate::windows_utils::{ register_rightclick_directory, register_rightclick_file, unregister_rightclick, @@ -198,52 +199,38 @@ impl From for UiCommand { } } -pub fn start_ui_command_handler(running: Arc, mut ui_command_receiver: UnboundedReceiver, nvim: Arc>) { - let serial_tx = start_serial_command_handler(running.clone(), nvim.clone()); - +pub fn start_ui_command_handler(mut ui_command_receiver: UnboundedReceiver, nvim: Arc>) { + let (serial_tx, mut serial_rx) = unbounded_channel::(); + let ui_command_nvim = nvim.clone(); tokio::spawn(async move { - loop { - if !running.load(Ordering::Relaxed) { - break; - } - + while RUNNING_TRACKER.is_running() { match ui_command_receiver.recv().await { Some(UiCommand::Serial(serial_command)) => serial_tx.send(serial_command).expect("Could not send serial ui command"), Some(UiCommand::Parallel(parallel_command)) => { - let nvim = nvim.clone(); + let ui_command_nvim = ui_command_nvim.clone(); tokio::spawn(async move { - parallel_command.execute(&nvim).await; + parallel_command.execute(&ui_command_nvim).await; }); } None => { - running.store(false, Ordering::Relaxed); - break; + RUNNING_TRACKER.quit("ui command channel failed"); } } } }); -} -pub fn start_serial_command_handler(running: Arc, nvim: Arc>) -> UnboundedSender { - let (serial_tx, mut serial_rx) = unbounded_channel::(); + let serial_command_nvim = nvim.clone(); tokio::spawn(async move { - loop { - if !running.load(Ordering::Relaxed) { - break; - } - + while RUNNING_TRACKER.is_running() { match serial_rx.recv().await { Some(serial_command) => { - serial_command.execute(&nvim).await; + serial_command.execute(&serial_command_nvim).await; }, None => { - running.store(false, Ordering::Relaxed); - break; + RUNNING_TRACKER.quit("serial ui command channel failed"); }, } } }); - - serial_tx } diff --git a/src/main.rs b/src/main.rs index dce2e0d..62b9717 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,8 +21,9 @@ mod redraw_scheduler; mod renderer; mod settings; mod utils; +mod running_tracker; mod window; -pub mod windows_utils; +mod windows_utils; #[macro_use] extern crate derive_new; @@ -42,6 +43,8 @@ use settings::SETTINGS; use window::{create_window, KeyboardSettings, WindowSettings}; pub use channel_utils::*; +pub use running_tracker::*; +pub use windows_utils::*; fn main() { // ----------- @@ -137,8 +140,6 @@ fn main() { CursorSettings::register(); KeyboardSettings::register(); - let running = Arc::new(AtomicBool::new(true)); - let (redraw_event_sender, redraw_event_receiver) = unbounded_channel(); let logging_redraw_event_sender = LoggingTx::attach(redraw_event_sender, "redraw_event".to_owned()); @@ -161,7 +162,6 @@ fn main() { logging_ui_command_sender.clone(), ui_command_receiver, logging_redraw_event_sender, - running.clone(), ); start_editor( redraw_event_receiver, @@ -172,7 +172,6 @@ fn main() { batched_draw_command_receiver, window_command_receiver, logging_ui_command_sender, - running, ); } diff --git a/src/running_tracker.rs b/src/running_tracker.rs new file mode 100644 index 0000000..a68e816 --- /dev/null +++ b/src/running_tracker.rs @@ -0,0 +1,34 @@ +use std::sync::{ + Arc, + atomic::{ + AtomicBool, + Ordering, + }, +}; + +use log::info; + +lazy_static! { + pub static ref RUNNING_TRACKER: RunningTracker = RunningTracker::new(); +} + +pub struct RunningTracker { + running: Arc +} + +impl RunningTracker { + fn new() -> Self { + Self { + running: Arc::new(AtomicBool::new(true)) + } + } + + pub fn quit(&self, reason: &str) { + self.running.store(false, Ordering::Relaxed); + info!("Quit {}", reason); + } + + pub fn is_running(&self) -> bool { + self.running.load(Ordering::Relaxed) + } +} diff --git a/src/window/window_wrapper/mod.rs b/src/window/window_wrapper/mod.rs index 6623dfc..b44d77f 100644 --- a/src/window/window_wrapper/mod.rs +++ b/src/window/window_wrapper/mod.rs @@ -3,11 +3,7 @@ mod mouse_manager; mod renderer; use std::{ - sync::{ - atomic::{AtomicBool, Ordering}, - mpsc::Receiver, - Arc, - }, + sync::mpsc::Receiver, time::{Duration, Instant}, }; @@ -33,6 +29,7 @@ use crate::{ editor::WindowCommand, redraw_scheduler::REDRAW_SCHEDULER, renderer::Renderer, + running_tracker::*, settings::{maybe_save_window_size, SETTINGS}, utils::Dimensions, }; @@ -99,13 +96,13 @@ impl GlutinWindowWrapper { self.windowed_context.window().set_title(&self.title); } - pub fn handle_quit(&mut self, running: &Arc) { + pub fn handle_quit(&mut self) { if SETTINGS.get::().remote_tcp.is_none() { self.ui_command_sender .send(ParallelCommand::Quit.into()) .expect("Could not send quit command to bridge"); } else { - running.store(false, Ordering::Relaxed); + RUNNING_TRACKER.quit("window closed"); } } @@ -118,7 +115,7 @@ impl GlutinWindowWrapper { REDRAW_SCHEDULER.queue_next_frame(); } - pub fn handle_event(&mut self, event: Event<()>, running: &Arc) { + pub fn handle_event(&mut self, event: Event<()>) { self.keyboard_manager.handle_event(&event); self.mouse_manager.handle_event( &event, @@ -128,13 +125,13 @@ impl GlutinWindowWrapper { ); match event { Event::LoopDestroyed => { - self.handle_quit(running); + self.handle_quit(); } Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => { - self.handle_quit(running); + self.handle_quit(); } Event::WindowEvent { event: WindowEvent::ScaleFactorChanged { scale_factor, .. }, @@ -242,7 +239,6 @@ pub fn create_window( batched_draw_command_receiver: Receiver>, window_command_receiver: Receiver, ui_command_sender: LoggingTx, - running: Arc, ) { let icon = { let icon = load_from_memory(ICON).expect("Failed to parse icon data"); @@ -312,7 +308,7 @@ pub fn create_window( let mut previous_frame_start = Instant::now(); event_loop.run(move |e, _window_target, control_flow| { - if !running.load(Ordering::Relaxed) { + if RUNNING_TRACKER.is_running() { maybe_save_window_size(window_wrapper.saved_grid_size); std::process::exit(0); } @@ -321,7 +317,7 @@ pub fn create_window( window_wrapper.handle_window_commands(); window_wrapper.synchronize_settings(); - window_wrapper.handle_event(e, &running); + window_wrapper.handle_event(e); let refresh_rate = { SETTINGS.get::().refresh_rate as f32 }; let expected_frame_length_seconds = 1.0 / refresh_rate;