diff options
| author | Shawn Hoffman <godisgovernment@gmail.com> | 2017-06-22 05:42:14 -0700 |
|---|---|---|
| committer | Shawn Hoffman <godisgovernment@gmail.com> | 2017-06-25 20:47:30 -0700 |
| commit | ed8f293b4f4c340dc342e54532fcdd953056efab (patch) | |
| tree | 9fc62b2a22ab8623000f58def58fc78608e2703f /Source/Core | |
| parent | 88b442e1a85e1c477072a7e9302eafcbd866fbb8 (diff) | |
Change "blocking" BlockingLoop::Stop to give up and die after a timeout.
This fixes the global-static fifo object causing infinite hangs in some
cases. Notably, failure to initialize a graphics backend would result in
BlockingLoop::Prepare being called but never executing Run(), leaving the
object in a bad state.
Diffstat (limited to 'Source/Core')
| -rw-r--r-- | Source/Core/Common/BlockingLoop.h | 23 | ||||
| -rw-r--r-- | Source/Core/VideoCommon/Fifo.cpp | 2 |
2 files changed, 21 insertions, 4 deletions
diff --git a/Source/Core/Common/BlockingLoop.h b/Source/Core/Common/BlockingLoop.h index a1ebe7d708..f8e9f85164 100644 --- a/Source/Core/Common/BlockingLoop.h +++ b/Source/Core/Common/BlockingLoop.h @@ -22,8 +22,15 @@ namespace Common class BlockingLoop { public: + enum StopMode + { + kNonBlock, + kBlock, + kBlockAndGiveUp, + }; + BlockingLoop() { m_stopped.Set(); } - ~BlockingLoop() { Stop(); } + ~BlockingLoop() { Stop(kBlockAndGiveUp); } // Triggers to rerun the payload of the Run() function at least once again. // This function will never block and is designed to finish as fast as possible. void Wakeup() @@ -192,7 +199,7 @@ public: // Quits the main loop. // By default, it will wait until the main loop quits. // Be careful to not use the blocking way within the payload of the Run() method. - void Stop(bool block = true) + void Stop(StopMode mode = kBlock) { if (m_stopped.IsSet()) return; @@ -202,8 +209,18 @@ public: // We have to interrupt the sleeping call to let the worker shut down soon. Wakeup(); - if (block) + switch (mode) + { + case kBlock: Wait(); + break; + case kBlockAndGiveUp: + WaitYield(std::chrono::milliseconds(100), [&] { + // If timed out, assume no one will come along to call Run, so force a break + m_stopped.Set(); + }); + break; + } } bool IsRunning() const { return !m_stopped.IsSet() && !m_shutdown.IsSet(); } diff --git a/Source/Core/VideoCommon/Fifo.cpp b/Source/Core/VideoCommon/Fifo.cpp index cedbea5432..15a1853ee7 100644 --- a/Source/Core/VideoCommon/Fifo.cpp +++ b/Source/Core/VideoCommon/Fifo.cpp @@ -144,7 +144,7 @@ void ExitGpuLoop() // Terminate GPU thread loop s_emu_running_state.Set(); - s_gpu_mainloop.Stop(false); + s_gpu_mainloop.Stop(s_gpu_mainloop.kNonBlock); } void EmulatorState(bool running) |
