Make the emulation stop asynchronous to prevent deadlocks.

This may expose bugs which relied on the Main Thread to be suspended in the stopping state.
This commit is contained in:
Jules Blok
2014-06-20 02:43:57 +02:00
parent ff6fa68b71
commit 3266394dfb
7 changed files with 127 additions and 82 deletions

View File

@ -425,6 +425,7 @@ CFrame::CFrame(wxFrame* parent,
Movie::SetInputManip(TASManipFunction);
State::SetOnAfterLoadCallback(OnAfterLoadCallback);
Core::SetOnStoppedCallback(OnStoppedCallback);
// Setup perspectives
if (g_pCodeWindow)
@ -692,6 +693,10 @@ void CFrame::OnHostMessage(wxCommandEvent& event)
case WM_USER_STOP:
DoStop();
break;
case IDM_STOPPED:
OnStopped();
break;
}
}
@ -904,6 +909,16 @@ void OnAfterLoadCallback()
}
}
void OnStoppedCallback()
{
// warning: this gets called from the EmuThread, so we should only queue things to do on the proper thread
if (main_frame)
{
wxCommandEvent event(wxEVT_HOST_COMMAND, IDM_STOPPED);
main_frame->GetEventHandler()->AddPendingEvent(event);
}
}
void TASManipFunction(SPADStatus *PadStatus, int controllerID)
{
if (main_frame)

View File

@ -123,6 +123,7 @@ public:
void InitBitmaps();
void DoPause();
void DoStop();
void OnStopped();
void DoRecordingSave();
void UpdateGUI();
void UpdateGameList();
@ -353,6 +354,7 @@ private:
int GetCmdForHotkey(unsigned int key);
void OnAfterLoadCallback();
void OnStoppedCallback();
// For TASInputDlg
void TASManipFunction(SPADStatus *PadStatus, int controllerID);

View File

@ -1120,72 +1120,77 @@ void CFrame::DoStop()
wxBeginBusyCursor();
BootManager::Stop();
wxEndBusyCursor();
confirmStop = false;
}
}
void CFrame::OnStopped()
{
wxEndBusyCursor();
confirmStop = false;
#if defined(HAVE_X11) && HAVE_X11
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bDisableScreenSaver)
X11Utils::InhibitScreensaver(X11Utils::XDisplayFromHandle(GetHandle()),
X11Utils::XWindowFromHandle(GetHandle()), false);
#endif
m_RenderFrame->SetTitle(StrToWxStr(scm_rev_str));
m_RenderFrame->SetTitle(StrToWxStr(scm_rev_str));
// Destroy the renderer frame when not rendering to main
m_RenderParent->Unbind(wxEVT_SIZE, &CFrame::OnRenderParentResize, this);
// Destroy the renderer frame when not rendering to main
m_RenderParent->Unbind(wxEVT_SIZE, &CFrame::OnRenderParentResize, this);
// Keyboard
wxTheApp->Unbind(wxEVT_KEY_DOWN, &CFrame::OnKeyDown, this);
wxTheApp->Unbind(wxEVT_KEY_UP, &CFrame::OnKeyUp, this);
// Keyboard
wxTheApp->Unbind(wxEVT_KEY_DOWN, &CFrame::OnKeyDown, this);
wxTheApp->Unbind(wxEVT_KEY_UP, &CFrame::OnKeyUp, this);
// Mouse
wxTheApp->Unbind(wxEVT_RIGHT_DOWN, &CFrame::OnMouse, this);
wxTheApp->Unbind(wxEVT_RIGHT_UP, &CFrame::OnMouse, this);
wxTheApp->Unbind(wxEVT_MIDDLE_DOWN, &CFrame::OnMouse, this);
wxTheApp->Unbind(wxEVT_MIDDLE_UP, &CFrame::OnMouse, this);
wxTheApp->Unbind(wxEVT_MOTION, &CFrame::OnMouse, this);
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor)
m_RenderParent->SetCursor(wxNullCursor);
DoFullscreen(false);
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain)
{
m_RenderFrame->Destroy();
}
else
{
// Mouse
wxTheApp->Unbind(wxEVT_RIGHT_DOWN, &CFrame::OnMouse, this);
wxTheApp->Unbind(wxEVT_RIGHT_UP, &CFrame::OnMouse, this);
wxTheApp->Unbind(wxEVT_MIDDLE_DOWN, &CFrame::OnMouse, this);
wxTheApp->Unbind(wxEVT_MIDDLE_UP, &CFrame::OnMouse, this);
wxTheApp->Unbind(wxEVT_MOTION, &CFrame::OnMouse, this);
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor)
m_RenderParent->SetCursor(wxNullCursor);
DoFullscreen(false);
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain)
{
m_RenderFrame->Destroy();
}
else
{
#if defined(__APPLE__)
// Disable the full screen button when not in a game.
NSView *view = (NSView *) m_RenderFrame->GetHandle();
NSWindow *window = [view window];
// Disable the full screen button when not in a game.
NSView *view = (NSView *)m_RenderFrame->GetHandle();
NSWindow *window = [view window];
[window setCollectionBehavior:NSWindowCollectionBehaviorDefault];
[window setCollectionBehavior : NSWindowCollectionBehaviorDefault];
#endif
// Make sure the window is not longer set to stay on top
m_RenderFrame->SetWindowStyle(m_RenderFrame->GetWindowStyle() & ~wxSTAY_ON_TOP);
}
m_RenderParent = nullptr;
// Clean framerate indications from the status bar.
GetStatusBar()->SetStatusText(" ", 0);
// Clear wiimote connection status from the status bar.
GetStatusBar()->SetStatusText(" ", 1);
// If batch mode was specified on the command-line, exit now.
if (m_bBatchMode)
Close(true);
// If using auto size with render to main, reset the application size.
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain &&
SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderWindowAutoSize)
SetSize(SConfig::GetInstance().m_LocalCoreStartupParameter.iWidth,
SConfig::GetInstance().m_LocalCoreStartupParameter.iHeight);
m_GameListCtrl->Enable();
m_GameListCtrl->Show();
m_GameListCtrl->SetFocus();
UpdateGUI();
// Make sure the window is not longer set to stay on top
m_RenderFrame->SetWindowStyle(m_RenderFrame->GetWindowStyle() & ~wxSTAY_ON_TOP);
}
m_RenderParent = nullptr;
// Clean framerate indications from the status bar.
GetStatusBar()->SetStatusText(" ", 0);
// Clear wiimote connection status from the status bar.
GetStatusBar()->SetStatusText(" ", 1);
// If batch mode was specified on the command-line, exit now.
if (m_bBatchMode)
Close(true);
// If using auto size with render to main, reset the application size.
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain &&
SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderWindowAutoSize)
SetSize(SConfig::GetInstance().m_LocalCoreStartupParameter.iWidth,
SConfig::GetInstance().m_LocalCoreStartupParameter.iHeight);
m_GameListCtrl->Enable();
m_GameListCtrl->Show();
m_GameListCtrl->SetFocus();
UpdateGUI();
}
void CFrame::DoRecordingSave()

View File

@ -254,6 +254,7 @@ enum
IDM_PANIC,
IDM_KEYSTATE,
IDM_WINDOWSIZEREQUEST,
IDM_STOPPED,
IDM_HOST_MESSAGE,
IDM_MPANEL, ID_STATUSBAR,

View File

@ -37,6 +37,7 @@
#include "Common/Logging/LogManager.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/CoreParameter.h"
#include "Core/Movie.h"
#include "Core/HW/Wiimote.h"
@ -455,6 +456,7 @@ int DolphinApp::OnExit()
VideoBackend::ClearList();
SConfig::Shutdown();
LogManager::Shutdown();
Core::Shutdown();
delete m_locale;