mirror of
https://github.com/SourMesen/Mesen2.git
synced 2025-04-02 10:21:44 -04:00
Fixed more issues with debugger when reloading games, etc.
This commit is contained in:
parent
972fc6a18b
commit
8f3f14d323
7 changed files with 110 additions and 62 deletions
|
@ -373,6 +373,11 @@ void Debugger::BreakRequest(bool release)
|
|||
}
|
||||
}
|
||||
|
||||
void Debugger::ResetSuspendCounter()
|
||||
{
|
||||
_suspendRequestCount = 0;
|
||||
}
|
||||
|
||||
void Debugger::SuspendDebugger(bool release)
|
||||
{
|
||||
if(release) {
|
||||
|
|
|
@ -104,6 +104,7 @@ public:
|
|||
|
||||
bool HasBreakRequest();
|
||||
void BreakRequest(bool release);
|
||||
void ResetSuspendCounter();
|
||||
void SuspendDebugger(bool release);
|
||||
|
||||
void BreakImmediately(BreakSource source);
|
||||
|
|
|
@ -258,26 +258,6 @@ void Emulator::RunSingleFrame()
|
|||
_controlManager->UpdateControlDevices();*/
|
||||
}
|
||||
|
||||
shared_ptr<Debugger> Emulator::SafeGetDebugger()
|
||||
{
|
||||
auto lock = _debuggerLock.AcquireSafe();
|
||||
shared_ptr<Debugger> debugger = _debugger;
|
||||
return debugger;
|
||||
}
|
||||
|
||||
void Emulator::SafeResetDebugger(Debugger* dbg = nullptr)
|
||||
{
|
||||
if(_emulationThreadId == std::this_thread::get_id()) {
|
||||
auto dbgLock = _debuggerLock.AcquireSafe();
|
||||
_debugger.reset(dbg);
|
||||
} else {
|
||||
//Need to pause emulator to change _debugger (when not called from the emulation thread)
|
||||
auto emuLock = AcquireLock();
|
||||
auto dbgLock = _debuggerLock.AcquireSafe();
|
||||
_debugger.reset(dbg);
|
||||
}
|
||||
}
|
||||
|
||||
void Emulator::Stop(bool sendNotification)
|
||||
{
|
||||
BlockDebuggerRequests();
|
||||
|
@ -286,11 +266,7 @@ void Emulator::Stop(bool sendNotification)
|
|||
|
||||
_notificationManager->SendNotification(ConsoleNotificationType::BeforeGameUnload);
|
||||
|
||||
shared_ptr<Debugger> debugger = SafeGetDebugger();
|
||||
if(debugger) {
|
||||
debugger->SuspendDebugger(false);
|
||||
debugger->Run();
|
||||
}
|
||||
ResetDebugger();
|
||||
|
||||
if(_emuThread) {
|
||||
_emuThread->join();
|
||||
|
@ -306,10 +282,6 @@ void Emulator::Stop(bool sendNotification)
|
|||
_notificationManager->SendNotification(ConsoleNotificationType::BeforeEmulationStop);
|
||||
}
|
||||
|
||||
//Make sure we release both pointers to destroy the debugger before everything else
|
||||
_debugger.reset();
|
||||
debugger.reset();
|
||||
|
||||
_videoDecoder->StopThread();
|
||||
_videoRenderer->StopThread();
|
||||
_rewindManager.reset();
|
||||
|
@ -359,12 +331,15 @@ bool Emulator::LoadRom(VirtualFile romFile, VirtualFile patchFile, bool stopRom,
|
|||
return false;
|
||||
}
|
||||
|
||||
BlockDebuggerRequests();
|
||||
|
||||
//Keep a reference to the original debugger, and reset the member to avoid any calls to the debugger by the init process
|
||||
shared_ptr<Debugger> debugger = SafeGetDebugger();
|
||||
//Keep a reference to the original debugger
|
||||
shared_ptr<Debugger> debugger = _debugger.lock();
|
||||
bool debuggerActive = debugger != nullptr;
|
||||
SafeResetDebugger();
|
||||
|
||||
//Unset _debugger to ensure nothing calls the debugger while initializing the new rom
|
||||
{
|
||||
auto dbgLock = _debuggerLock.AcquireSafe();
|
||||
ResetDebugger();
|
||||
}
|
||||
|
||||
if(patchFile.IsValid()) {
|
||||
if(romFile.ApplyPatch(patchFile)) {
|
||||
|
@ -415,7 +390,8 @@ bool Emulator::LoadRom(VirtualFile romFile, VirtualFile patchFile, bool stopRom,
|
|||
|
||||
if(result != LoadRomResult::Success) {
|
||||
MessageManager::DisplayMessage("Error", "CouldNotLoadFile", romFile.GetFileName());
|
||||
_debugger = debugger;
|
||||
_debugger.reset(debugger);
|
||||
debugger->ResetSuspendCounter();
|
||||
_allowDebuggerRequest = true;
|
||||
return false;
|
||||
}
|
||||
|
@ -605,7 +581,7 @@ double Emulator::GetFrameDelay()
|
|||
|
||||
void Emulator::PauseOnNextFrame()
|
||||
{
|
||||
shared_ptr<Debugger> debugger = _debugger;
|
||||
shared_ptr<Debugger> debugger = _debugger.lock();
|
||||
if(debugger) {
|
||||
switch(GetConsoleType()) {
|
||||
case ConsoleType::Snes:
|
||||
|
@ -629,7 +605,7 @@ void Emulator::PauseOnNextFrame()
|
|||
|
||||
void Emulator::Pause()
|
||||
{
|
||||
shared_ptr<Debugger> debugger = _debugger;
|
||||
shared_ptr<Debugger> debugger = _debugger.lock();
|
||||
if(debugger) {
|
||||
switch(GetConsoleType()) {
|
||||
case ConsoleType::Snes:
|
||||
|
@ -652,7 +628,7 @@ void Emulator::Pause()
|
|||
|
||||
void Emulator::Resume()
|
||||
{
|
||||
shared_ptr<Debugger> debugger = _debugger;
|
||||
shared_ptr<Debugger> debugger = _debugger.lock();
|
||||
if(debugger) {
|
||||
debugger->Run();
|
||||
} else {
|
||||
|
@ -662,7 +638,7 @@ void Emulator::Resume()
|
|||
|
||||
bool Emulator::IsPaused()
|
||||
{
|
||||
shared_ptr<Debugger> debugger = _debugger;
|
||||
shared_ptr<Debugger> debugger = _debugger.lock();
|
||||
if(debugger) {
|
||||
return debugger->IsExecutionStopped();
|
||||
} else {
|
||||
|
@ -701,7 +677,7 @@ EmulatorLock Emulator::AcquireLock()
|
|||
|
||||
void Emulator::Lock()
|
||||
{
|
||||
shared_ptr<Debugger> debugger = _debugger;
|
||||
shared_ptr<Debugger> debugger = _debugger.lock();
|
||||
if(debugger) {
|
||||
debugger->SuspendDebugger(false);
|
||||
}
|
||||
|
@ -712,7 +688,7 @@ void Emulator::Lock()
|
|||
|
||||
void Emulator::Unlock()
|
||||
{
|
||||
shared_ptr<Debugger> debugger = _debugger;
|
||||
shared_ptr<Debugger> debugger = _debugger.lock();
|
||||
if(debugger) {
|
||||
debugger->SuspendDebugger(true);
|
||||
}
|
||||
|
@ -737,7 +713,7 @@ void Emulator::WaitForLock()
|
|||
//Spin wait until we are allowed to start again
|
||||
while(_lockCounter > 0 && !_stopFlag) {}
|
||||
|
||||
shared_ptr<Debugger> debugger = _debugger;
|
||||
shared_ptr<Debugger> debugger = _debugger.lock();
|
||||
if(debugger) {
|
||||
while(debugger->HasBreakRequest() && !_stopFlag) {}
|
||||
}
|
||||
|
@ -870,24 +846,41 @@ void Emulator::BlockDebuggerRequests()
|
|||
Emulator::DebuggerRequest Emulator::GetDebugger(bool autoInit)
|
||||
{
|
||||
if(IsRunning() && _allowDebuggerRequest) {
|
||||
auto lock = _debuggerLock.AcquireSafe();
|
||||
if(IsRunning() && _allowDebuggerRequest) {
|
||||
if(!_debugger && autoInit) {
|
||||
InitDebugger();
|
||||
}
|
||||
return DebuggerRequest(this);
|
||||
if(!_debugger && autoInit) {
|
||||
InitDebugger();
|
||||
}
|
||||
return DebuggerRequest(this);
|
||||
}
|
||||
return DebuggerRequest(nullptr);
|
||||
}
|
||||
|
||||
void Emulator::ResetDebugger(Debugger* dbg)
|
||||
{
|
||||
BlockDebuggerRequests();
|
||||
|
||||
shared_ptr<Debugger> currentDbg = _debugger.lock();
|
||||
if(currentDbg) {
|
||||
currentDbg->SuspendDebugger(false);
|
||||
}
|
||||
|
||||
if(_emulationThreadId == std::this_thread::get_id()) {
|
||||
_debugger.reset(dbg);
|
||||
} else {
|
||||
//Need to pause emulator to change _debugger (when not called from the emulation thread)
|
||||
auto emuLock = AcquireLock();
|
||||
_debugger.reset(dbg);
|
||||
}
|
||||
|
||||
_allowDebuggerRequest = true;
|
||||
}
|
||||
|
||||
void Emulator::InitDebugger()
|
||||
{
|
||||
if(!_debugger) {
|
||||
//Lock to make sure we don't try to start debuggers in 2 separate threads at once
|
||||
auto lock = _debuggerLock.AcquireSafe();
|
||||
if(!_debugger) {
|
||||
SafeResetDebugger(new Debugger(this, _console.get()));
|
||||
ResetDebugger(new Debugger(this, _console.get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -898,23 +891,16 @@ void Emulator::StopDebugger()
|
|||
_paused = IsPaused();
|
||||
|
||||
if(_debugger) {
|
||||
BlockDebuggerRequests();
|
||||
|
||||
auto lock = _debuggerLock.AcquireSafe();
|
||||
if(_debugger) {
|
||||
_debugger->SuspendDebugger(false);
|
||||
Lock();
|
||||
_debugger.reset();
|
||||
Unlock();
|
||||
ResetDebugger();
|
||||
}
|
||||
|
||||
_allowDebuggerRequest = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool Emulator::IsDebugging()
|
||||
{
|
||||
return SafeGetDebugger() != nullptr;
|
||||
return !!_debugger;
|
||||
}
|
||||
|
||||
thread::id Emulator::GetEmulationThreadId()
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "Core/Shared/Interfaces/IConsole.h"
|
||||
#include "Core/Shared/Audio/AudioPlayerTypes.h"
|
||||
#include "Utilities/Timer.h"
|
||||
#include "Utilities/safe_ptr.h"
|
||||
#include "Utilities/SimpleLock.h"
|
||||
#include "Utilities/VirtualFile.h"
|
||||
|
||||
|
@ -57,7 +58,7 @@ private:
|
|||
|
||||
shared_ptr<ShortcutKeyHandler> _shortcutKeyHandler;
|
||||
shared_ptr<RewindManager> _rewindManager;
|
||||
shared_ptr<Debugger> _debugger;
|
||||
safe_ptr<Debugger> _debugger;
|
||||
shared_ptr<SystemActionManager> _systemActionManager;
|
||||
|
||||
const unique_ptr<EmuSettings> _settings;
|
||||
|
@ -108,8 +109,7 @@ private:
|
|||
void RunFrameWithRunAhead();
|
||||
|
||||
void BlockDebuggerRequests();
|
||||
shared_ptr<Debugger> SafeGetDebugger();
|
||||
void SafeResetDebugger(Debugger* dbg);
|
||||
void ResetDebugger(Debugger* dbg = nullptr);
|
||||
|
||||
public:
|
||||
class DebuggerRequest
|
||||
|
@ -123,7 +123,7 @@ public:
|
|||
{
|
||||
if(emu) {
|
||||
_emu = emu;
|
||||
_debugger = _emu->_debugger;
|
||||
_debugger = _emu->_debugger.lock();
|
||||
_emu->_debugRequestCount++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -465,6 +465,7 @@
|
|||
<ClInclude Include="Patches\UpsPatcher.h" />
|
||||
<ClInclude Include="PlatformUtilities.h" />
|
||||
<ClInclude Include="PNGHelper.h" />
|
||||
<ClInclude Include="safe_ptr.h" />
|
||||
<ClInclude Include="Scale2x\scale2x.h" />
|
||||
<ClInclude Include="Scale2x\scale3x.h" />
|
||||
<ClInclude Include="Scale2x\scalebit.h" />
|
||||
|
|
|
@ -229,6 +229,9 @@
|
|||
<ClInclude Include="spng.h">
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="safe_ptr.h">
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="xBRZ\xbrz.cpp">
|
||||
|
|
52
Utilities/safe_ptr.h
Normal file
52
Utilities/safe_ptr.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
#include "stdafx.h"
|
||||
|
||||
template<typename T>
|
||||
class safe_ptr
|
||||
{
|
||||
private:
|
||||
T* _ptr = nullptr;
|
||||
shared_ptr<T> _shared;
|
||||
SimpleLock _lock;
|
||||
|
||||
public:
|
||||
safe_ptr(T* ptr = nullptr)
|
||||
{
|
||||
reset(ptr);
|
||||
}
|
||||
|
||||
~safe_ptr()
|
||||
{
|
||||
//shared_ptr will free the instance as needed
|
||||
}
|
||||
|
||||
shared_ptr<T> lock()
|
||||
{
|
||||
auto lock = _lock.AcquireSafe();
|
||||
return _shared;
|
||||
}
|
||||
|
||||
void reset(T* ptr = nullptr)
|
||||
{
|
||||
auto lock = _lock.AcquireSafe();
|
||||
_ptr = ptr;
|
||||
_shared.reset(ptr);
|
||||
}
|
||||
|
||||
void reset(shared_ptr<T> ptr)
|
||||
{
|
||||
auto lock = _lock.AcquireSafe();
|
||||
_ptr = ptr.get();
|
||||
_shared = ptr;
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return _ptr != nullptr;
|
||||
}
|
||||
|
||||
T* operator->() const
|
||||
{
|
||||
//Accessing the pointer this way is fast, but not thread-safe
|
||||
return _ptr;
|
||||
}
|
||||
};
|
Loading…
Add table
Reference in a new issue