Fix EmuThread loop by ensuring it exits properly.

Note: There is a pre-existing issue with booting a new game in that it keeps the old EmuThread.
The GL code now supports this but the Core still doesn't.
This commit is contained in:
Sacha 2014-08-25 01:49:34 +10:00
parent a3a70e56ac
commit b044510fa9
2 changed files with 29 additions and 9 deletions

View file

@ -20,7 +20,8 @@
EmuThread::EmuThread(GRenderWindow* render_window) : EmuThread::EmuThread(GRenderWindow* render_window) :
exec_cpu_step(false), cpu_running(false), exec_cpu_step(false), cpu_running(false),
render_window(render_window), filename("") render_window(render_window), filename(""),
stop_run(false)
{ {
} }
@ -31,6 +32,7 @@ void EmuThread::SetFilename(std::string filename)
void EmuThread::run() void EmuThread::run()
{ {
stop_run = false;
while (true) while (true)
{ {
for (int tight_loop = 0; tight_loop < 10000; ++tight_loop) for (int tight_loop = 0; tight_loop < 10000; ++tight_loop)
@ -41,11 +43,17 @@ void EmuThread::run()
exec_cpu_step = false; exec_cpu_step = false;
Core::SingleStep(); Core::SingleStep();
if (!cpu_running) if (!cpu_running) {
emit CPUStepped(); emit CPUStepped();
yieldCurrentThread();
}
} }
} }
QMutexLocker lock(&mutex);
if (stop_run)
break;
} }
render_window->moveContext();
Core::Stop(); Core::Stop();
} }
@ -58,16 +66,24 @@ void EmuThread::Stop()
return; return;
} }
{
QMutexLocker lock(&mutex);
stop_run = true;
}
//core::g_state = core::SYS_DIE; //core::g_state = core::SYS_DIE;
wait(1000); wait(500);
if (isRunning()) if (isRunning())
{ {
WARN_LOG(MASTER_LOG, "EmuThread still running, terminating..."); WARN_LOG(MASTER_LOG, "EmuThread still running, terminating...");
terminate(); quit();
wait(1000); wait(1000);
if (isRunning()) if (isRunning())
{
WARN_LOG(MASTER_LOG, "EmuThread STILL running, something is wrong here..."); WARN_LOG(MASTER_LOG, "EmuThread STILL running, something is wrong here...");
terminate();
}
} }
INFO_LOG(MASTER_LOG, "EmuThread stopped"); INFO_LOG(MASTER_LOG, "EmuThread stopped");
} }
@ -116,7 +132,6 @@ GRenderWindow::GRenderWindow(QWidget* parent) : QWidget(parent), emu_thread(this
layout->setMargin(0); layout->setMargin(0);
setLayout(layout); setLayout(layout);
QObject::connect(&emu_thread, SIGNAL(started()), this, SLOT(moveContext())); QObject::connect(&emu_thread, SIGNAL(started()), this, SLOT(moveContext()));
QObject::connect(&emu_thread, SIGNAL(finished()), this, SLOT(moveContext()));
BackupGeometry(); BackupGeometry();
} }
@ -127,13 +142,14 @@ void GRenderWindow::moveContext()
// We need to move GL context to the swapping thread in Qt5 // We need to move GL context to the swapping thread in Qt5
#if QT_VERSION > QT_VERSION_CHECK(5, 0, 0) #if QT_VERSION > QT_VERSION_CHECK(5, 0, 0)
// If the thread started running, move the GL Context to the new thread. Otherwise, move it back. // If the thread started running, move the GL Context to the new thread. Otherwise, move it back.
child->context()->moveToThread(emu_thread.isRunning() ? &emu_thread : qApp->thread()); child->context()->moveToThread((QThread::currentThread() == qApp->thread()) ? &emu_thread : qApp->thread());
#endif #endif
} }
GRenderWindow::~GRenderWindow() GRenderWindow::~GRenderWindow()
{ {
emu_thread.Stop(); if (emu_thread.isRunning())
emu_thread.Stop();
} }
void GRenderWindow::SwapBuffers() void GRenderWindow::SwapBuffers()
@ -144,7 +160,8 @@ void GRenderWindow::SwapBuffers()
void GRenderWindow::closeEvent(QCloseEvent* event) void GRenderWindow::closeEvent(QCloseEvent* event)
{ {
emu_thread.Stop(); if (emu_thread.isRunning())
emu_thread.Stop();
QWidget::closeEvent(event); QWidget::closeEvent(event);
} }

View file

@ -1,3 +1,4 @@
#include <QMutex>
#include <QThread> #include <QThread>
#include <QGLWidget> #include <QGLWidget>
#include "common/common.h" #include "common/common.h"
@ -66,6 +67,8 @@ private:
bool exec_cpu_step; bool exec_cpu_step;
bool cpu_running; bool cpu_running;
bool stop_run;
QMutex mutex;
GRenderWindow* render_window; GRenderWindow* render_window;
@ -105,7 +108,7 @@ public:
void keyPressEvent(QKeyEvent* event); void keyPressEvent(QKeyEvent* event);
void keyReleaseEvent(QKeyEvent* event); void keyReleaseEvent(QKeyEvent* event);
private slots: public slots:
void moveContext(); void moveContext();
private: private: