summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorShawn Hoffman <godisgovernment@gmail.com>2017-06-22 05:42:14 -0700
committerShawn Hoffman <godisgovernment@gmail.com>2017-06-25 20:47:30 -0700
commited8f293b4f4c340dc342e54532fcdd953056efab (patch)
tree9fc62b2a22ab8623000f58def58fc78608e2703f /Source/Core
parent88b442e1a85e1c477072a7e9302eafcbd866fbb8 (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.h23
-rw-r--r--Source/Core/VideoCommon/Fifo.cpp2
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)