From 109d072cb63606bb0002cb9f9be81bf5584029f2 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 12 Feb 2020 23:47:04 -0500 Subject: [PATCH] Avoids trying to paper over huge gaps in running time. Also attempts to improve SDL shutdown reliability. --- .../Mac/Clock Signal/Machine/CSMachine.mm | 8 +++-- OSBindings/SDL/main.cpp | 29 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm index edb5eddd9..2130b06bb 100644 --- a/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm +++ b/OSBindings/Mac/Clock Signal/Machine/CSMachine.mm @@ -767,11 +767,15 @@ struct ActivityObserver: public Activity::Observer { __block auto lastTime = Time::nanos_now(); _timer = [[CSHighPrecisionTimer alloc] initWithTask:^{ - // Grab the time now and, therefore, the amount of time since the timer last fired. + // Grab the time now and, therefore, the amount of time since the timer last fired + // (capped at half a second). const auto timeNow = Time::nanos_now(); const auto duration = timeNow - lastTime; + if(duration > Time::Nanos(500'000'000)) { + lastTime = timeNow; + return; + } - CGSize pixelSize; BOOL splitAndSync = NO; @synchronized(self) { diff --git a/OSBindings/SDL/main.cpp b/OSBindings/SDL/main.cpp index 3b683fa21..dda4872f5 100644 --- a/OSBindings/SDL/main.cpp +++ b/OSBindings/SDL/main.cpp @@ -51,6 +51,14 @@ struct MachineRunner { void stop() { if(timer_) { + // SDL doesn't define whether SDL_RemoveTimer will block until any pending calls + // have been completed, or will return instantly. So: do an ordered shutdown, + // then remove the timer. + state_ = State::Stopping; + while(state_ == State::Stopping) { + frame_lock_.clear(); + } + SDL_RemoveTimer(timer_); timer_ = 0; } @@ -87,6 +95,13 @@ struct MachineRunner { std::atomic vsync_time_; std::atomic_flag frame_lock_; + enum class State { + Running, + Stopping, + Stopped + }; + std::atomic state_ = State::Running; + Time::ScanSynchroniser scan_synchroniser_; // A slightly clumsy means of trying to derive frame rate from calls to @@ -105,7 +120,21 @@ struct MachineRunner { } void update() { + // If a shutdown is in progress, signal stoppage and do nothing. + if(state_ != State::Running) { + state_ = State::Stopped; + return; + } + + // Get time now and determine how long it has been since the last time this + // function was called. If it's more than half a second then forego any activity + // now, as there's obviously been some sort of substantial time glitch. const auto time_now = Time::nanos_now(); + if(time_now - last_time_ > Time::Nanos(500'000'000)) { + last_time_ = time_now; + return; + } + const auto vsync_time = vsync_time_.load(); std::unique_lock lock_guard(*machine_mutex);