From 946289544d9917650bf359ea966d5a0f4f9aa04c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kr=C3=BCger?= Date: Sun, 9 Nov 2025 07:03:57 +0100 Subject: [PATCH] Add frequent exit checks throughout render loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The issue was that sleep() was blocking for 16-33ms without checking the exit flag. Now: - Check should_exit at 5 points in the render loop - Break sleep into 5ms chunks, checking between each chunk - This gives <5ms response time to exit commands Exit responds within 5ms: Press 'q', ESC, or Ctrl+C 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/animation/renderer.rs | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/animation/renderer.rs b/src/animation/renderer.rs index 233fb30..a17a5d3 100644 --- a/src/animation/renderer.rs +++ b/src/animation/renderer.rs @@ -65,17 +65,22 @@ impl<'a> Renderer<'a> { }); loop { - let frame_start = std::time::Instant::now(); - - // Check if user requested exit + // Check for exit FIRST if should_exit.load(Ordering::Relaxed) { break; } + let frame_start = std::time::Instant::now(); + // Calculate progress with easing let linear_progress = timeline.progress(); let eased_progress = self.easing.ease(linear_progress); + // Check again before rendering + if should_exit.load(Ordering::Relaxed) { + break; + } + // Apply effect let effect_result = self.effect.apply(self.ascii_art, eased_progress); @@ -86,6 +91,11 @@ impl<'a> Renderer<'a> { effect_result.text.clone() }; + // Check before terminal operations + if should_exit.load(Ordering::Relaxed) { + break; + } + // Render to terminal terminal.clear()?; terminal.refresh_size()?; @@ -117,6 +127,11 @@ impl<'a> Renderer<'a> { } } + // Check if user wants to exit + if should_exit.load(Ordering::Relaxed) { + break; + } + // Check if animation is complete before advancing if timeline.is_complete() { break; @@ -128,7 +143,19 @@ impl<'a> Renderer<'a> { let elapsed = frame_start.elapsed(); if elapsed < frame_duration { - sleep(frame_duration - elapsed).await; + let sleep_duration = frame_duration - elapsed; + // Break sleep into small chunks to check should_exit frequently + let chunk_duration = Duration::from_millis(5); + let mut remaining = sleep_duration; + + while remaining > Duration::ZERO { + if should_exit.load(Ordering::Relaxed) { + break; + } + let sleep_time = remaining.min(chunk_duration); + sleep(sleep_time).await; + remaining = remaining.saturating_sub(sleep_time); + } } }