From a63e78d83cda1e6f3afabfc152a979b9d3d27e67 Mon Sep 17 00:00:00 2001
From: Stenzek <stenzek@gmail.com>
Date: Sat, 10 Feb 2024 23:18:49 +0900
Subject: [PATCH] Qt: Mutate breakpoints on CPU thread

---
 src/duckstation-qt/debuggerwindow.cpp | 38 ++++++++++++++++-----------
 src/duckstation-qt/debuggerwindow.h   |  2 ++
 2 files changed, 25 insertions(+), 15 deletions(-)

diff --git a/src/duckstation-qt/debuggerwindow.cpp b/src/duckstation-qt/debuggerwindow.cpp
index 54d8e8ee6..2b08d86a2 100644
--- a/src/duckstation-qt/debuggerwindow.cpp
+++ b/src/duckstation-qt/debuggerwindow.cpp
@@ -553,26 +553,30 @@ void DebuggerWindow::setMemoryViewRegion(Bus::MemoryRegion region)
 
 void DebuggerWindow::toggleBreakpoint(VirtualMemoryAddress address)
 {
-  const bool new_bp_state = !CPU::HasBreakpointAtAddress(address);
-  if (new_bp_state)
-  {
-    if (!CPU::AddBreakpoint(address, false))
-      return;
-  }
-  else
-  {
-    if (!CPU::RemoveBreakpoint(address))
-      return;
-  }
+  Host::RunOnCPUThread([this, address]() {
+    const bool new_bp_state = !CPU::HasBreakpointAtAddress(address);
+    if (new_bp_state)
+    {
+      if (!CPU::AddBreakpoint(address, false))
+        return;
+    }
+    else
+    {
+      if (!CPU::RemoveBreakpoint(address))
+        return;
+    }
 
-  m_code_model->setBreakpointState(address, new_bp_state);
-  refreshBreakpointList();
+    QtHost::RunOnUIThread([this, address, new_bp_state, bps = CPU::GetBreakpointList()]() {
+      m_code_model->setBreakpointState(address, new_bp_state);
+      refreshBreakpointList(bps);
+    });
+  });
 }
 
 void DebuggerWindow::clearBreakpoints()
 {
   m_code_model->clearBreakpoints();
-  CPU::ClearBreakpoints();
+  Host::RunOnCPUThread(&CPU::ClearBreakpoints);
 }
 
 std::optional<VirtualMemoryAddress> DebuggerWindow::getSelectedCodeAddress()
@@ -614,11 +618,15 @@ bool DebuggerWindow::scrollToMemoryAddress(VirtualMemoryAddress address)
 }
 
 void DebuggerWindow::refreshBreakpointList()
+{
+  refreshBreakpointList(CPU::GetBreakpointList());
+}
+
+void DebuggerWindow::refreshBreakpointList(const CPU::BreakpointList& bps)
 {
   while (m_ui.breakpointsWidget->topLevelItemCount() > 0)
     delete m_ui.breakpointsWidget->takeTopLevelItem(0);
 
-  const CPU::BreakpointList bps(CPU::GetBreakpointList());
   for (const CPU::Breakpoint& bp : bps)
   {
     QTreeWidgetItem* item = new QTreeWidgetItem();
diff --git a/src/duckstation-qt/debuggerwindow.h b/src/duckstation-qt/debuggerwindow.h
index 7b47e21de..ac68d056e 100644
--- a/src/duckstation-qt/debuggerwindow.h
+++ b/src/duckstation-qt/debuggerwindow.h
@@ -5,6 +5,7 @@
 
 #include "ui_debuggerwindow.h"
 
+#include "core/cpu_core.h"
 #include "core/types.h"
 
 #include <QtWidgets/QMainWindow>
@@ -76,6 +77,7 @@ private:
   void scrollToCodeAddress(VirtualMemoryAddress address);
   bool scrollToMemoryAddress(VirtualMemoryAddress address);
   void refreshBreakpointList();
+  void refreshBreakpointList(const CPU::BreakpointList& bps);
 
   Ui::DebuggerWindow m_ui;