Core: Make RunOnCPUThread always non-blocking.
This commit is contained in:
@@ -825,8 +825,7 @@ static void RestoreStateAndUnlock(Core::System& system, const bool unpause_on_un
|
|||||||
system.GetCPU().RestoreStateAndUnlock(unpause_on_unlock);
|
system.GetCPU().RestoreStateAndUnlock(unpause_on_unlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunOnCPUThread(Core::System& system, Common::MoveOnlyFunction<void()> function,
|
void RunOnCPUThread(Core::System& system, Common::MoveOnlyFunction<void()> function)
|
||||||
bool wait_for_completion)
|
|
||||||
{
|
{
|
||||||
if (IsCPUThread())
|
if (IsCPUThread())
|
||||||
{
|
{
|
||||||
@@ -834,8 +833,6 @@ void RunOnCPUThread(Core::System& system, Common::MoveOnlyFunction<void()> funct
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::OneShotEvent cpu_thread_job_finished;
|
|
||||||
|
|
||||||
// Pause the CPU (set it to stepping mode).
|
// Pause the CPU (set it to stepping mode).
|
||||||
const bool was_running = PauseAndLock(system);
|
const bool was_running = PauseAndLock(system);
|
||||||
|
|
||||||
@@ -843,15 +840,6 @@ void RunOnCPUThread(Core::System& system, Common::MoveOnlyFunction<void()> funct
|
|||||||
{
|
{
|
||||||
// If the core hasn't been started, there is no active CPU thread we can race against.
|
// If the core hasn't been started, there is no active CPU thread we can race against.
|
||||||
function();
|
function();
|
||||||
wait_for_completion = false;
|
|
||||||
}
|
|
||||||
else if (wait_for_completion)
|
|
||||||
{
|
|
||||||
// Queue the job function followed by triggering the event.
|
|
||||||
system.GetCPU().AddCPUThreadJob([&function, &cpu_thread_job_finished] {
|
|
||||||
function();
|
|
||||||
cpu_thread_job_finished.Set();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -861,14 +849,6 @@ void RunOnCPUThread(Core::System& system, Common::MoveOnlyFunction<void()> funct
|
|||||||
|
|
||||||
// Release the CPU thread, and let it execute the callback.
|
// Release the CPU thread, and let it execute the callback.
|
||||||
RestoreStateAndUnlock(system, was_running);
|
RestoreStateAndUnlock(system, was_running);
|
||||||
|
|
||||||
// If we're waiting for completion, block until the event fires.
|
|
||||||
if (wait_for_completion)
|
|
||||||
{
|
|
||||||
// Periodically yield to the UI thread, so we don't deadlock.
|
|
||||||
while (!cpu_thread_job_finished.WaitFor(std::chrono::milliseconds(10)))
|
|
||||||
Host_YieldToUI();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Callbacks for backends / engine ---
|
// --- Callbacks for backends / engine ---
|
||||||
|
|||||||
@@ -158,8 +158,7 @@ void FrameUpdateOnCPUThread();
|
|||||||
void OnFrameEnd(Core::System& system);
|
void OnFrameEnd(Core::System& system);
|
||||||
|
|
||||||
// Run a function on the CPU thread, asynchronously.
|
// Run a function on the CPU thread, asynchronously.
|
||||||
void RunOnCPUThread(Core::System& system, Common::MoveOnlyFunction<void()> function,
|
void RunOnCPUThread(Core::System& system, Common::MoveOnlyFunction<void()> function);
|
||||||
bool wait_for_completion);
|
|
||||||
|
|
||||||
// for calling back into UI code without introducing a dependency on it in core
|
// for calling back into UI code without introducing a dependency on it in core
|
||||||
using StateChangedCallbackFunc = std::function<void(Core::State)>;
|
using StateChangedCallbackFunc = std::function<void(Core::State)>;
|
||||||
|
|||||||
+10
-24
@@ -496,11 +496,9 @@ static void SaveAsFromCore(Core::System& system, std::string filename)
|
|||||||
void SaveAs(Core::System& system, std::string filename)
|
void SaveAs(Core::System& system, std::string filename)
|
||||||
{
|
{
|
||||||
Core::RunOnCPUThread(
|
Core::RunOnCPUThread(
|
||||||
system,
|
system, [&system, filename = std::move(filename), lock = GetStateSaveTaskLock()]() mutable {
|
||||||
[&system, filename = std::move(filename), lock = GetStateSaveTaskLock()]() mutable {
|
|
||||||
SaveAsFromCore(system, std::move(filename));
|
SaveAsFromCore(system, std::move(filename));
|
||||||
},
|
});
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool GetVersionFromLZO(StateHeader& header, File::IOFile& f)
|
static bool GetVersionFromLZO(StateHeader& header, File::IOFile& f)
|
||||||
@@ -873,12 +871,9 @@ void LoadAs(Core::System& system, std::string filename)
|
|||||||
if (!CheckIfStateLoadIsAllowed(system))
|
if (!CheckIfStateLoadIsAllowed(system))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Core::RunOnCPUThread(
|
Core::RunOnCPUThread(system, [&system, filename = std::move(filename)]() mutable {
|
||||||
system,
|
|
||||||
[&system, filename = std::move(filename)]() mutable {
|
|
||||||
LoadAsFromCore(system, std::move(filename));
|
LoadAsFromCore(system, std::move(filename));
|
||||||
},
|
});
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetOnAfterLoadCallback(AfterLoadCallbackFunc callback)
|
void SetOnAfterLoadCallback(AfterLoadCallbackFunc callback)
|
||||||
@@ -919,9 +914,7 @@ void LoadLastSaved(Core::System& system, int i)
|
|||||||
if (!CheckIfStateLoadIsAllowed(system))
|
if (!CheckIfStateLoadIsAllowed(system))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Core::RunOnCPUThread(
|
Core::RunOnCPUThread(system, [&system, i] {
|
||||||
system,
|
|
||||||
[&system, i] {
|
|
||||||
// Data must reach the filesystem for up to date "UsedSlots".
|
// Data must reach the filesystem for up to date "UsedSlots".
|
||||||
s_compress_and_dump_thread.WaitForCompletion();
|
s_compress_and_dump_thread.WaitForCompletion();
|
||||||
|
|
||||||
@@ -934,15 +927,12 @@ void LoadLastSaved(Core::System& system, int i)
|
|||||||
|
|
||||||
std::ranges::stable_sort(used_slots, std::ranges::greater{}, &SlotWithTimestamp::timestamp);
|
std::ranges::stable_sort(used_slots, std::ranges::greater{}, &SlotWithTimestamp::timestamp);
|
||||||
LoadAsFromCore(system, MakeStateFilename(used_slots[i].slot));
|
LoadAsFromCore(system, MakeStateFilename(used_slots[i].slot));
|
||||||
},
|
});
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveFirstSaved(Core::System& system)
|
void SaveFirstSaved(Core::System& system)
|
||||||
{
|
{
|
||||||
Core::RunOnCPUThread(
|
Core::RunOnCPUThread(system, [&system, lock = GetStateSaveTaskLock()] {
|
||||||
system,
|
|
||||||
[&system, lock = GetStateSaveTaskLock()] {
|
|
||||||
// Data must reach the filesystem for up to date "UsedSlots".
|
// Data must reach the filesystem for up to date "UsedSlots".
|
||||||
s_compress_and_dump_thread.WaitForCompletion();
|
s_compress_and_dump_thread.WaitForCompletion();
|
||||||
|
|
||||||
@@ -956,8 +946,7 @@ void SaveFirstSaved(Core::System& system)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SaveAsFromCore(system, MakeStateFilename(*slot));
|
SaveAsFromCore(system, MakeStateFilename(*slot));
|
||||||
},
|
});
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the last state before loading the state
|
// Load the last state before loading the state
|
||||||
@@ -966,9 +955,7 @@ void UndoLoadState(Core::System& system)
|
|||||||
if (!CheckIfStateLoadIsAllowed(system))
|
if (!CheckIfStateLoadIsAllowed(system))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Core::RunOnCPUThread(
|
Core::RunOnCPUThread(system, [&system] {
|
||||||
system,
|
|
||||||
[&system] {
|
|
||||||
if (s_undo_load_buffer.empty())
|
if (s_undo_load_buffer.empty())
|
||||||
{
|
{
|
||||||
PanicAlertFmtT("There is nothing to undo!");
|
PanicAlertFmtT("There is nothing to undo!");
|
||||||
@@ -994,8 +981,7 @@ void UndoLoadState(Core::System& system)
|
|||||||
{
|
{
|
||||||
LoadFromBuffer(system, s_undo_load_buffer);
|
LoadFromBuffer(system, s_undo_load_buffer);
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the state that the last save state overwritten on
|
// Load the state that the last save state overwritten on
|
||||||
|
|||||||
@@ -37,9 +37,7 @@
|
|||||||
|
|
||||||
static void RestartCore(const std::weak_ptr<HW::GBA::Core>& core, std::string_view rom_path = {})
|
static void RestartCore(const std::weak_ptr<HW::GBA::Core>& core, std::string_view rom_path = {})
|
||||||
{
|
{
|
||||||
Core::RunOnCPUThread(
|
Core::RunOnCPUThread(Core::System::GetInstance(), [core, rom_path = std::string(rom_path)] {
|
||||||
Core::System::GetInstance(),
|
|
||||||
[core, rom_path = std::string(rom_path)] {
|
|
||||||
if (auto core_ptr = core.lock())
|
if (auto core_ptr = core.lock())
|
||||||
{
|
{
|
||||||
auto& info = Config::MAIN_GBA_ROM_PATHS[core_ptr->GetCoreInfo().device_number];
|
auto& info = Config::MAIN_GBA_ROM_PATHS[core_ptr->GetCoreInfo().device_number];
|
||||||
@@ -52,19 +50,15 @@ static void RestartCore(const std::weak_ptr<HW::GBA::Core>& core, std::string_vi
|
|||||||
Config::SetCurrent(info, Config::GetBase(info));
|
Config::SetCurrent(info, Config::GetBase(info));
|
||||||
core_ptr->Start(core_timing.GetTicks());
|
core_ptr->Start(core_timing.GetTicks());
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void QueueEReaderCard(const std::weak_ptr<HW::GBA::Core>& core, std::string_view card_path)
|
static void QueueEReaderCard(const std::weak_ptr<HW::GBA::Core>& core, std::string_view card_path)
|
||||||
{
|
{
|
||||||
Core::RunOnCPUThread(
|
Core::RunOnCPUThread(Core::System::GetInstance(), [core, card_path = std::string(card_path)] {
|
||||||
Core::System::GetInstance(),
|
|
||||||
[core, card_path = std::string(card_path)] {
|
|
||||||
if (auto core_ptr = core.lock())
|
if (auto core_ptr = core.lock())
|
||||||
core_ptr->EReaderQueueCard(card_path);
|
core_ptr->EReaderQueueCard(card_path);
|
||||||
},
|
});
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GBAWidget::GBAWidget(std::weak_ptr<HW::GBA::Core> core, const HW::GBA::CoreInfo& info,
|
GBAWidget::GBAWidget(std::weak_ptr<HW::GBA::Core> core, const HW::GBA::CoreInfo& info,
|
||||||
@@ -161,13 +155,11 @@ void GBAWidget::ToggleDisconnect()
|
|||||||
|
|
||||||
m_force_disconnect = !m_force_disconnect;
|
m_force_disconnect = !m_force_disconnect;
|
||||||
|
|
||||||
Core::RunOnCPUThread(
|
Core::RunOnCPUThread(Core::System::GetInstance(),
|
||||||
Core::System::GetInstance(),
|
|
||||||
[core = m_core, force_disconnect = m_force_disconnect] {
|
[core = m_core, force_disconnect = m_force_disconnect] {
|
||||||
if (auto core_ptr = core.lock())
|
if (auto core_ptr = core.lock())
|
||||||
core_ptr->SetForceDisconnect(force_disconnect);
|
core_ptr->SetForceDisconnect(force_disconnect);
|
||||||
},
|
});
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAWidget::LoadROM()
|
void GBAWidget::LoadROM()
|
||||||
@@ -224,8 +216,7 @@ void GBAWidget::DoState(bool export_state)
|
|||||||
if (state_path.isEmpty())
|
if (state_path.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Core::RunOnCPUThread(
|
Core::RunOnCPUThread(Core::System::GetInstance(),
|
||||||
Core::System::GetInstance(),
|
|
||||||
[export_state, core = m_core, state_path = state_path.toStdString()] {
|
[export_state, core = m_core, state_path = state_path.toStdString()] {
|
||||||
if (auto core_ptr = core.lock())
|
if (auto core_ptr = core.lock())
|
||||||
{
|
{
|
||||||
@@ -234,8 +225,7 @@ void GBAWidget::DoState(bool export_state)
|
|||||||
else
|
else
|
||||||
core_ptr->ImportState(state_path);
|
core_ptr->ImportState(state_path);
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAWidget::ImportExportSave(bool export_save)
|
void GBAWidget::ImportExportSave(bool export_save)
|
||||||
@@ -255,8 +245,7 @@ void GBAWidget::ImportExportSave(bool export_save)
|
|||||||
if (save_path.isEmpty())
|
if (save_path.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Core::RunOnCPUThread(
|
Core::RunOnCPUThread(Core::System::GetInstance(),
|
||||||
Core::System::GetInstance(),
|
|
||||||
[export_save, core = m_core, save_path = save_path.toStdString()] {
|
[export_save, core = m_core, save_path = save_path.toStdString()] {
|
||||||
if (auto core_ptr = core.lock())
|
if (auto core_ptr = core.lock())
|
||||||
{
|
{
|
||||||
@@ -265,8 +254,7 @@ void GBAWidget::ImportExportSave(bool export_save)
|
|||||||
else
|
else
|
||||||
core_ptr->ImportSave(save_path);
|
core_ptr->ImportSave(save_path);
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBAWidget::Resize(int scale)
|
void GBAWidget::Resize(int scale)
|
||||||
|
|||||||
Reference in New Issue
Block a user