Core: Use RAII for EmuThread shutdown

This is more reliable, as this guarantees subsystems will be
shut down in the same order they were initialised (if they were
initialised). It also allows us to stop keeping track of what needs to
be shut down manually and just return in case of errors.

This should prevent the emulator from getting totally stuck when
the boot process does fail.
This commit is contained in:
Léo Lam 2017-05-27 18:48:40 +02:00
parent 0ff8e2b36f
commit 52f00603e2
1 changed files with 36 additions and 33 deletions

View File

@ -24,6 +24,7 @@
#include "Common/Logging/LogManager.h"
#include "Common/MemoryUtil.h"
#include "Common/MsgHandler.h"
#include "Common/ScopeGuard.h"
#include "Common/StringUtil.h"
#include "Common/Thread.h"
#include "Common/Timer.h"
@ -453,6 +454,19 @@ static void EmuThread()
{
const SConfig& core_parameter = SConfig::GetInstance();
s_is_booting.Set();
Common::ScopeGuard flag_guard{[] {
s_is_booting.Clear();
s_is_started = false;
s_is_stopping = false;
if (s_on_stopped_callback)
s_on_stopped_callback();
INFO_LOG(CONSOLE, "Stop\t\t---- Shutdown complete ----");
}};
// Prevent the UI from getting stuck whenever an error occurs.
Common::ScopeGuard stop_message_guard{[] { Host_Message(WM_USER_STOP); }};
Common::SetCurrentThreadName("Emuthread - Starting");
@ -466,16 +480,23 @@ static void EmuThread()
DeclareAsCPUThread();
Movie::Init();
Common::ScopeGuard movie_guard{Movie::Shutdown};
HW::Init();
Common::ScopeGuard hw_guard{[] {
// We must set up this flag before executing HW::Shutdown()
s_hardware_initialized = false;
INFO_LOG(CONSOLE, "%s", StopMessage(false, "Shutting down HW").c_str());
HW::Shutdown();
INFO_LOG(CONSOLE, "%s", StopMessage(false, "HW shutdown").c_str());
}};
if (!g_video_backend->Initialize(s_window_handle))
{
s_is_booting.Clear();
PanicAlert("Failed to initialize video backend!");
Host_Message(WM_USER_STOP);
return;
}
Common::ScopeGuard video_guard{[] { g_video_backend->Shutdown(); }};
OSD::AddMessage("Dolphin " + g_video_backend->GetName() + " Video Backend.", 5000);
@ -486,11 +507,7 @@ static void EmuThread()
if (!DSP::GetDSPEmulator()->Initialize(core_parameter.bWii, core_parameter.bDSPThread))
{
s_is_booting.Clear();
HW::Shutdown();
g_video_backend->Shutdown();
PanicAlert("Failed to initialize DSP emulation!");
Host_Message(WM_USER_STOP);
return;
}
@ -520,7 +537,18 @@ static void EmuThread()
Wiimote::LoadConfig();
}
Common::ScopeGuard controller_guard{[init_controllers] {
if (!init_controllers)
return;
Wiimote::Shutdown();
Keyboard::Shutdown();
Pad::Shutdown();
g_controller_interface.Shutdown();
}};
AudioCommon::InitSoundStream();
Common::ScopeGuard audio_guard{AudioCommon::ShutdownSoundStream};
// The hardware is initialized.
s_hardware_initialized = true;
@ -617,40 +645,15 @@ static void EmuThread()
if (core_parameter.bCPUThread)
g_video_backend->Video_Cleanup();
// We must set up this flag before executing HW::Shutdown()
s_hardware_initialized = false;
INFO_LOG(CONSOLE, "%s", StopMessage(false, "Shutting down HW").c_str());
HW::Shutdown();
INFO_LOG(CONSOLE, "%s", StopMessage(false, "HW shutdown").c_str());
if (init_controllers)
{
Wiimote::Shutdown();
Keyboard::Shutdown();
Pad::Shutdown();
g_controller_interface.Shutdown();
init_controllers = false;
}
g_video_backend->Shutdown();
AudioCommon::ShutdownSoundStream();
INFO_LOG(CONSOLE, "%s", StopMessage(true, "Main Emu thread stopped").c_str());
// Clear on screen messages that haven't expired
OSD::ClearMessages();
BootManager::RestoreConfig();
INFO_LOG(CONSOLE, "Stop [Video Thread]\t\t---- Shutdown complete ----");
Movie::Shutdown();
PatchEngine::Shutdown();
HLE::Clear();
s_is_stopping = false;
if (s_on_stopped_callback)
s_on_stopped_callback();
// If we shut down normally, the stop message does not need to be triggered.
stop_message_guard.Dismiss();
}
// Set or get the running state