diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 3fdcfae9ab..6c44f6a6bb 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -3895,6 +3895,40 @@ bool Emulator::Quit(bool force_quit) void Emulator::CleanUp() { + // Signal threads + if (auto rsx = g_fxo->try_get()) + { + *static_cast(rsx) = thread_state::aborting; + } + + for (const auto& [type, data] : *g_fxo) + { + if (type.thread_op) + { + type.thread_op(data, thread_state::aborting); + } + } + + // Join threads + qt_events_aware_op(50, [&]() + { + bool has_running = false; + + for (const auto& [type, data] : *g_fxo) + { + if (type.thread_op) + { + if (type.thread_op(data, thread_state::aborting) != thread_state::finished) + { + has_running = true; + break; + } + } + } + + return has_running == false; + }); + // Deinitialize object manager to prevent any hanging objects at program exit g_fxo->clear(); } diff --git a/rpcs3/util/fixed_typemap.hpp b/rpcs3/util/fixed_typemap.hpp index bcb5f36baa..abb6fe9c57 100644 --- a/rpcs3/util/fixed_typemap.hpp +++ b/rpcs3/util/fixed_typemap.hpp @@ -71,7 +71,7 @@ namespace stx struct typeinfo { bool(*create)(uchar* ptr, manual_typemap&, utils::serial*, std::string_view) noexcept = nullptr; - void(*thread_op)(void* ptr, thread_state) noexcept = nullptr; + thread_state(*thread_op)(void* ptr, thread_state) noexcept = nullptr; void(*save)(void* ptr, utils::serial&) noexcept = nullptr; bool(*saveable)(bool) noexcept = nullptr; void(*destroy)(void* ptr) noexcept = nullptr; @@ -137,10 +137,20 @@ namespace stx } template - static void call_thread_op(void* ptr, thread_state state) noexcept + static thread_state call_thread_op(void* ptr, thread_state state) noexcept { // Abort and/or join (expected thread_state::aborting or thread_state::finished) *std::launder(static_cast(ptr)) = state; + + if constexpr (std::is_convertible_v) + { + return *std::launder(static_cast(ptr)); + } + else + { + constexpr thread_state context_finished{3}; + return context_finished; + } } template