Merge pull request #5660 from shuffle2/unblock-blockingloop

Change "blocking" BlockingLoop::Stop to give up and die after a timeout.
This commit is contained in:
Markus Wick 2017-06-26 10:23:21 +02:00 committed by GitHub
commit 99b1735424
2 changed files with 21 additions and 4 deletions

View File

@ -22,8 +22,15 @@ namespace Common
class BlockingLoop class BlockingLoop
{ {
public: public:
enum StopMode
{
kNonBlock,
kBlock,
kBlockAndGiveUp,
};
BlockingLoop() { m_stopped.Set(); } BlockingLoop() { m_stopped.Set(); }
~BlockingLoop() { Stop(); } ~BlockingLoop() { Stop(kBlockAndGiveUp); }
// Triggers to rerun the payload of the Run() function at least once again. // 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. // This function will never block and is designed to finish as fast as possible.
void Wakeup() void Wakeup()
@ -192,7 +199,7 @@ public:
// Quits the main loop. // Quits the main loop.
// By default, it will wait until the main loop quits. // 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. // 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()) if (m_stopped.IsSet())
return; return;
@ -202,8 +209,18 @@ public:
// We have to interrupt the sleeping call to let the worker shut down soon. // We have to interrupt the sleeping call to let the worker shut down soon.
Wakeup(); Wakeup();
if (block) switch (mode)
{
case kBlock:
Wait(); 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(); } bool IsRunning() const { return !m_stopped.IsSet() && !m_shutdown.IsSet(); }

View File

@ -144,7 +144,7 @@ void ExitGpuLoop()
// Terminate GPU thread loop // Terminate GPU thread loop
s_emu_running_state.Set(); s_emu_running_state.Set();
s_gpu_mainloop.Stop(false); s_gpu_mainloop.Stop(s_gpu_mainloop.kNonBlock);
} }
void EmulatorState(bool running) void EmulatorState(bool running)