From e4ea133717a5292339c134160da984ba186d3de8 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Tue, 28 Apr 2015 19:03:01 -0400
Subject: [PATCH] Qt: Restructured to remove unnecessary shutdown event and
 various cleanups.

---
 src/citra_qt/bootmanager.cpp           | 43 +++----------------------
 src/citra_qt/bootmanager.h             | 44 +++++++-------------------
 src/citra_qt/debugger/disassembler.cpp | 10 +++---
 src/citra_qt/main.cpp                  | 33 ++++++++++---------
 4 files changed, 40 insertions(+), 90 deletions(-)

diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp
index fa4e976f4..1e902a8b6 100644
--- a/src/citra_qt/bootmanager.cpp
+++ b/src/citra_qt/bootmanager.cpp
@@ -28,9 +28,8 @@
 #define COPYRIGHT       "Copyright (C) 2013-2014 Citra Team"
 
 EmuThread::EmuThread(GRenderWindow* render_window) :
-    exec_cpu_step(false), cpu_running(false), stop_run(false), render_window(render_window) {
+    exec_step(false), running(false), stop_run(false), render_window(render_window) {
 
-    shutdown_event.Reset();
     connect(this, SIGNAL(started()), render_window, SLOT(moveContext()));
 }
 
@@ -42,20 +41,20 @@ void EmuThread::run() {
     // next execution step
     bool was_active = false;
     while (!stop_run) {
-        if (cpu_running) {
+        if (running) {
             if (!was_active)
                 emit DebugModeLeft();
 
             Core::RunLoop();
 
-            was_active = cpu_running || exec_cpu_step;
+            was_active = running || exec_step;
             if (!was_active)
                 emit DebugModeEntered();
-        } else if (exec_cpu_step) {
+        } else if (exec_step) {
             if (!was_active)
                 emit DebugModeLeft();
 
-            exec_cpu_step = false;
+            exec_step = false;
             Core::SingleStep();
             emit DebugModeEntered();
             yieldCurrentThread();
@@ -65,40 +64,8 @@ void EmuThread::run() {
     }
 
     render_window->moveContext();
-
-    shutdown_event.Set();
 }
 
-void EmuThread::Stop() {
-    if (!isRunning()) {
-        LOG_WARNING(Frontend, "EmuThread::Stop called while emu thread wasn't running, returning...");
-        return;
-    }
-    stop_run = true;
-
-    // Release emu threads from any breakpoints, so that this doesn't hang forever.
-    Pica::g_debug_context->ClearBreakpoints();
-
-    //core::g_state = core::SYS_DIE;
-
-    // TODO: Waiting here is just a bad workaround for retarded shutdown logic.
-    wait(1000);
-    if (isRunning()) {
-        LOG_WARNING(Frontend, "EmuThread still running, terminating...");
-        quit();
-
-        // TODO: Waiting 50 seconds can be necessary if the logging subsystem has a lot of spam
-        // queued... This should be fixed.
-        wait(50000);
-        if (isRunning()) {
-            LOG_CRITICAL(Frontend, "EmuThread STILL running, something is wrong here...");
-            terminate();
-        }
-    }
-    LOG_INFO(Frontend, "EmuThread stopped");
-}
-
-
 // This class overrides paintEvent and resizeEvent to prevent the GUI thread from stealing GL context.
 // The corresponding functionality is handled in EmuThread instead
 class GGLWidgetInternal : public QGLWidget
diff --git a/src/citra_qt/bootmanager.h b/src/citra_qt/bootmanager.h
index f6f09773c..e9b3ea664 100644
--- a/src/citra_qt/bootmanager.h
+++ b/src/citra_qt/bootmanager.h
@@ -25,66 +25,46 @@ public:
 
     /**
      * Start emulation (on new thread)
-     *
      * @warning Only call when not running!
      */
     void run() override;
 
     /**
-     * Allow the CPU to process a single instruction (if cpu is not running)
-     *
+     * Steps the emulation thread by a single CPU instruction (if the CPU is not already running)
      * @note This function is thread-safe
      */
-    void ExecStep() { exec_cpu_step = true; }
+    void ExecStep() { exec_step = true; }
 
     /**
-     * Sets whether the CPU is running 
-     *
+     * Sets whether the emulation thread is running or not
+     * @param running Boolean value, set the emulation thread to running if true
      * @note This function is thread-safe
      */
-    void SetCpuRunning(bool running) { cpu_running = running; }
+    void SetRunning(bool running) { this->running = running; }
 
     /**
-     * Allow the CPU to continue processing instructions without interruption
-     *
+     * Check if the emulation thread is running or not
+     * @return True if the emulation thread is running, otherwise false
      * @note This function is thread-safe
      */
-    bool IsCpuRunning() { return cpu_running; }
-
+    bool IsRunning() { return running; }
 
     /**
-     * Shutdown (permantently stops) the CPU
+     * Shutdown (permanently stops) the emulation thread
      */
-    void ShutdownCpu() { stop_run = true; };
-
-    /**
-     * Waits for the CPU shutdown to complete
-     */
-    void WaitForCpuShutdown() { shutdown_event.Wait(); }
-
-
-public slots:
-    /**
-     * Stop emulation and wait for the thread to finish.
-     *
-     * @details: This function will wait a second for the thread to finish; if it hasn't finished until then, we'll terminate() it and wait another second, hoping that it will be terminated by then.
-     * @note: This function is thread-safe.
-     */
-    void Stop();
+    void Shutdown() { stop_run = true; };
 
 private:
     friend class GMainWindow;
 
     EmuThread(GRenderWindow* render_window);
 
-    bool exec_cpu_step;
-    bool cpu_running;
+    bool exec_step;
+    bool running;
     std::atomic<bool> stop_run;
 
     GRenderWindow* render_window;
 
-    Common::Event shutdown_event;
-
 signals:
     /**
      * Emitted when the CPU has halted execution
diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp
index b58edafe7..f9423e1d6 100644
--- a/src/citra_qt/debugger/disassembler.cpp
+++ b/src/citra_qt/debugger/disassembler.cpp
@@ -201,7 +201,7 @@ void DisassemblerWidget::Init()
 
 void DisassemblerWidget::OnContinue()
 {
-    main_window.GetEmuThread()->SetCpuRunning(true);
+    main_window.GetEmuThread()->SetRunning(true);
 }
 
 void DisassemblerWidget::OnStep()
@@ -211,13 +211,13 @@ void DisassemblerWidget::OnStep()
 
 void DisassemblerWidget::OnStepInto()
 {
-    main_window.GetEmuThread()->SetCpuRunning(false);
+    main_window.GetEmuThread()->SetRunning(false);
     main_window.GetEmuThread()->ExecStep();
 }
 
 void DisassemblerWidget::OnPause()
 {
-    main_window.GetEmuThread()->SetCpuRunning(false);
+    main_window.GetEmuThread()->SetRunning(false);
 
     // TODO: By now, the CPU might not have actually stopped...
     if (Core::g_app_core) {
@@ -227,7 +227,7 @@ void DisassemblerWidget::OnPause()
 
 void DisassemblerWidget::OnToggleStartStop()
 {
-    main_window.GetEmuThread()->SetCpuRunning(!main_window.GetEmuThread()->IsCpuRunning());
+    main_window.GetEmuThread()->SetRunning(!main_window.GetEmuThread()->IsRunning());
 }
 
 void DisassemblerWidget::OnDebugModeEntered()
@@ -235,7 +235,7 @@ void DisassemblerWidget::OnDebugModeEntered()
     ARMword next_instr = Core::g_app_core->GetPC();
 
     if (model->GetBreakPoints().IsAddressBreakPoint(next_instr))
-        main_window.GetEmuThread()->SetCpuRunning(false);
+        main_window.GetEmuThread()->SetRunning(false);
 
     model->SetNextInstruction(next_instr);
 
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index 5441c17f1..dd180baa4 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -199,10 +199,6 @@ void GMainWindow::OnDisplayTitleBars(bool show)
 void GMainWindow::BootGame(std::string filename) {
     LOG_INFO(Frontend, "Citra starting...\n");
 
-    // Shutdown previous session if the emu thread is still active...
-    if (emu_thread != nullptr)
-        ShutdownGame();
-
     System::Init(render_window);
 
     // Load a game or die...
@@ -222,29 +218,36 @@ void GMainWindow::BootGame(std::string filename) {
 }
 
 void GMainWindow::ShutdownGame() {
-    emu_thread->SetCpuRunning(false);
-
-    emu_thread->ShutdownCpu();
-    emu_thread->WaitForCpuShutdown();
-    emu_thread->Stop();
-
+    // Shutdown the emulation thread and wait for it to complete
+    emu_thread->SetRunning(false);
+    emu_thread->Shutdown();
+    emu_thread->wait();
     delete emu_thread;
     emu_thread = nullptr;
 
+    // Release emu threads from any breakpoints
+    Pica::g_debug_context->ClearBreakpoints();
+
+    // Shutdown the core emulation
     System::Shutdown();
 
+    // Update the GUI
     ui.action_Start->setEnabled(true);
     ui.action_Pause->setEnabled(false);
     ui.action_Stop->setEnabled(false);
-
     render_window->hide();
 }
 
 void GMainWindow::OnMenuLoadFile()
 {
     QString filename = QFileDialog::getOpenFileName(this, tr("Load File"), QString(), tr("3DS executable (*.3ds *.3dsx *.elf *.axf *.bin *.cci *.cxi)"));
-    if (filename.size())
-       BootGame(filename.toLatin1().data());
+    if (filename.size()) {
+        // Shutdown previous session if the emu thread is still active...
+        if (emu_thread != nullptr)
+            ShutdownGame();
+
+        BootGame(filename.toLatin1().data());
+    }
 }
 
 void GMainWindow::OnMenuLoadSymbolMap() {
@@ -255,7 +258,7 @@ void GMainWindow::OnMenuLoadSymbolMap() {
 
 void GMainWindow::OnStartGame()
 {
-    emu_thread->SetCpuRunning(true);
+    emu_thread->SetRunning(true);
 
     ui.action_Start->setEnabled(false);
     ui.action_Pause->setEnabled(true);
@@ -264,7 +267,7 @@ void GMainWindow::OnStartGame()
 
 void GMainWindow::OnPauseGame()
 {
-    emu_thread->SetCpuRunning(false);
+    emu_thread->SetRunning(false);
 
     ui.action_Start->setEnabled(true);
     ui.action_Pause->setEnabled(false);