diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 764e4acf89..a8bcf88895 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -2211,8 +2211,16 @@ thread_state thread_ctrl::state() { auto _this = g_tls_this_thread; + // Guard for recursive calls (TODO: may be more effective to reuse one of m_sync bits) + static thread_local bool s_tls_exec = false; + // Drain execution queue - _this->exec(); + if (!s_tls_exec) + { + s_tls_exec = true; + _this->exec(); + s_tls_exec = false; + } return static_cast(_this->m_sync & 3); } diff --git a/Utilities/Thread.h b/Utilities/Thread.h index ac5425ad57..929324de4c 100644 --- a/Utilities/Thread.h +++ b/Utilities/Thread.h @@ -344,6 +344,84 @@ private: static const u64 process_affinity_mask; }; +// Used internally +template +class thread_future_t : public thread_future, result_storage, Args...> +{ + [[no_unique_address]] decltype(std::make_tuple(std::forward(std::declval())...)) m_args; + + [[no_unique_address]] Ctx m_func; + + using future = thread_future_t; + +public: + thread_future_t(Ctx&& func, Args&&... args) + : m_args(std::forward(args)...) + , m_func(std::forward(func)) + { + thread_future::exec.raw() = +[](thread_base* tb, thread_future* tf) + { + const auto _this = static_cast(tf); + + if (!tb) [[unlikely]] + { + if constexpr (!future::empty && !Discard) + { + _this->init(); + } + + return; + } + + if constexpr (future::empty || Discard) + { + std::apply(_this->m_func, std::move(_this->m_args)); + } + else + { + new (_this->_get()) decltype(auto)(std::apply(_this->m_func, std::move(_this->m_args))); + } + }; + } + + ~thread_future_t() + { + if constexpr (!future::empty && !Discard) + { + if (!this->exec) + { + this->destroy(); + } + } + } + + decltype(auto) get() + { + while (this->exec) + { + this->wait(); + } + + if constexpr (!future::empty && !Discard) + { + return *this->_get(); + } + } + + decltype(auto) get() const + { + while (this->exec) + { + this->wait(); + } + + if constexpr (!future::empty && !Discard) + { + return *this->_get(); + } + } +}; + // Derived from the callable object Context, possibly a lambda template class named_thread final : public Context, result_storage, thread_base @@ -467,74 +545,9 @@ public: if constexpr (v1) { - class future : public thread_future, result_storage - { - // A tuple to store arguments - decltype(std::make_tuple(std::forward(arg, args...))) m_args; + using future = thread_future_t; - public: - future(Arg&& arg, Args&&... args) - : m_args(std::forward(arg, args...)) - { - thread_future::exec.raw() = +[](thread_base* tb, thread_future* tf) - { - const auto _this = static_cast(tf); - - if (!tb) [[unlikely]] - { - if constexpr (!future::empty && !Discard) - { - _this->init(); - } - - return; - } - - if constexpr (future::empty || Discard) - { - std::apply(*static_cast(static_cast(tb)), _this->m_args); - } - else - { - new (_this->_get()) decltype(auto)(std::apply(*static_cast(static_cast(tb)), _this->m_args)); - } - }; - } - - future(const future&) = delete; - - future& operator=(const future&) = delete; - - ~future() - { - if constexpr (!future::empty && !Discard) - { - // Should be set to null if executed - if (!this->exec) - { - this->destroy(); - } - } - } - - decltype(auto) get() - { - if constexpr (!future::empty && !Discard) - { - return *this->_get(); - } - } - - decltype(auto) get() const - { - if constexpr (!future::empty && !Discard) - { - return *this->_get(); - } - } - }; - - single_ptr target = make_single(std::forward(arg, args...)); + single_ptr target = make_single(*static_cast(this), std::forward(arg), std::forward(args)...); if constexpr (!Discard) { @@ -553,75 +566,9 @@ public: } else if constexpr (v2) { - class future : public thread_future, result_storage, void, Args...> - { - decltype(std::make_tuple(std::forward(args...))) m_args; + using future = thread_future_t; - std::decay_t m_func; - - public: - future(Arg func, Args&&... args) - : m_args(std::forward(args...)) - , m_func(func) - { - thread_future::exec.raw() = +[](thread_base* tb, thread_future* tf) - { - const auto _this = static_cast(tf); - - if (!tb) [[unlikely]] - { - if constexpr (!future::empty && !Discard) - { - _this->init(); - } - - return; - } - - if constexpr (future::empty || Discard) - { - std::apply(_this->m_func, _this->m_args); - } - else - { - new (_this->_get()) decltype(auto)(std::apply(_this->m_func, _this->m_args)); - } - }; - } - - future(const future&) = delete; - - future& operator=(const future&) = delete; - - ~future() - { - if constexpr (!future::empty && !Discard) - { - if (!this->exec) - { - this->destroy(); - } - } - } - - decltype(auto) get() - { - if constexpr (!future::empty && !Discard) - { - return *this->_get(); - } - } - - decltype(auto) get() const - { - if constexpr (!future::empty && !Discard) - { - return *this->_get(); - } - } - }; - - single_ptr target = make_single(std::forward(arg, args...)); + single_ptr target = make_single(std::forward(arg), std::forward(args)...); if constexpr (!Discard) { @@ -637,75 +584,9 @@ public: } else if constexpr (v3) { - class future : public thread_future, result_storage, void, Context&, Args...> - { - decltype(std::make_tuple(std::forward(args...))) m_args; + using future = thread_future_t; - std::decay_t m_func; - - public: - future(Arg func, Args&&... args) - : m_args(std::forward(args...)) - , m_func(func) - { - thread_future::exec.raw() = +[](thread_base* tb, thread_future* tf) - { - const auto _this = static_cast(tf); - - if (!tb) [[unlikely]] - { - if constexpr (!future::empty && !Discard) - { - _this->init(); - } - - return; - } - - if constexpr (future::empty || Discard) - { - std::apply(_this->m_func, *static_cast(static_cast(tb)), _this->m_args); - } - else - { - new (_this->_get()) decltype(auto)(std::apply(_this->m_func, *static_cast(static_cast(tb)), _this->m_args)); - } - }; - } - - future(const future&) = delete; - - future& operator=(const future&) = delete; - - ~future() - { - if constexpr (!future::empty && !Discard) - { - if (!this->exec) - { - this->destroy(); - } - } - } - - decltype(auto) get() - { - if constexpr (!future::empty && !Discard) - { - return *this->_get(); - } - } - - decltype(auto) get() const - { - if constexpr (!future::empty && !Discard) - { - return *this->_get(); - } - } - }; - - single_ptr target = make_single(std::forward(arg, args...)); + single_ptr target = make_single(std::forward(arg), std::ref(*static_cast(this)), std::forward(args)...); if constexpr (!Discard) { diff --git a/rpcs3/Emu/RSX/Overlays/overlay_message_dialog.cpp b/rpcs3/Emu/RSX/Overlays/overlay_message_dialog.cpp index f08510ed72..9682cffc08 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_message_dialog.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_message_dialog.cpp @@ -166,6 +166,11 @@ namespace rsx close(true, true); } + struct msg_dialog_thread + { + static constexpr auto thread_name = "MsgDialog Thread"sv; + }; + error_code message_dialog::show(bool is_blocking, const std::string& text, const MsgDialogType& type, std::function on_close) { visible = false; @@ -246,7 +251,7 @@ namespace rsx { if (!exit) { - g_fxo->init("MsgDialog Thread", [&, tbit = alloc_thread_bit()]() + g_fxo->get>()->operator()([&, tbit = alloc_thread_bit()]() { g_thread_bit = tbit; diff --git a/rpcs3/Emu/RSX/Overlays/overlay_osk.cpp b/rpcs3/Emu/RSX/Overlays/overlay_osk.cpp index ce8bc88fe9..abbac7ebf6 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_osk.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_osk.cpp @@ -781,6 +781,11 @@ namespace rsx return m_cached_resource; } + struct osk_dialog_thread + { + static constexpr auto thread_name = "OSK Thread"sv; + }; + void osk_dialog::Create(const std::string& title, const std::u16string& message, char16_t* init_text, u32 charlimit, u32 prohibit_flags, u32 panel_flag, u32 first_view_panel) { state = OskDialogState::Open; @@ -1012,7 +1017,7 @@ namespace rsx update_panel(); - g_fxo->init("OSK Thread", [this, tbit = alloc_thread_bit()] + g_fxo->get>()->operator()([this, tbit = alloc_thread_bit()] { g_thread_bit = tbit; diff --git a/rpcs3/util/shared_ptr.hpp b/rpcs3/util/shared_ptr.hpp index b716bc860c..55c452fa84 100644 --- a/rpcs3/util/shared_ptr.hpp +++ b/rpcs3/util/shared_ptr.hpp @@ -10,6 +10,7 @@ namespace stx #pragma GCC diagnostic push #ifdef __clang__ #pragma GCC diagnostic ignored "-Wundefined-var-template" +#pragma GCC diagnostic ignored "-Wundefined-internal" #endif #endif @@ -21,7 +22,7 @@ namespace stx template constexpr bool is_same_ptr() noexcept { -#if !defined(_MSC_VER) && !defined(__clang__) +#ifdef _MSC_VER return true; #else if constexpr (std::is_void_v || std::is_void_v || std::is_same_v) @@ -30,14 +31,14 @@ namespace stx } else if constexpr (std::is_convertible_v) { - const auto u = std::addressof(sample); - const volatile void* x = u; + constexpr auto u = std::addressof(sample); + constexpr volatile void* x = u; return static_cast(u) == x; } else if constexpr (std::is_convertible_v) { - const auto t = std::addressof(sample); - const volatile void* x = t; + constexpr auto t = std::addressof(sample); + constexpr volatile void* x = t; return static_cast(t) == x; } else