diff --git a/rpcs3/Emu/Cell/lv2/sys_config.cpp b/rpcs3/Emu/Cell/lv2/sys_config.cpp index c39444ccd0..b254af8206 100644 --- a/rpcs3/Emu/Cell/lv2/sys_config.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_config.cpp @@ -133,6 +133,23 @@ lv2_config_service_event& lv2_config_service_event::operator=(thread_state s) no return *this; } +lv2_config_service_event::~lv2_config_service_event() noexcept +{ + operator=(thread_state::destroying_context); +} + +lv2_config::~lv2_config() noexcept +{ + for (auto& [key, event] : events) + { + if (event) + { + // Avoid collision with lv2_config_service_event destructor + event->m_destroyed = true; + } + } +} + // LV2 Config Service Listener bool lv2_config_service_listener::check_service(const lv2_config_service& service) const { diff --git a/rpcs3/Emu/Cell/lv2/sys_config.h b/rpcs3/Emu/Cell/lv2/sys_config.h index 3915dfc8cb..0d7fede8b1 100644 --- a/rpcs3/Emu/Cell/lv2/sys_config.h +++ b/rpcs3/Emu/Cell/lv2/sys_config.h @@ -161,6 +161,8 @@ public: return null_ptr; } + + ~lv2_config() noexcept; }; /* @@ -276,7 +278,7 @@ public: // Utilities usz get_size() const { return sizeof(sys_config_service_event_t)-1 + data.size(); } - shared_ptr get_shared_ptr () const { return idm::get_unlocked(idm_id); } + shared_ptr get_shared_ptr () const { return stx::make_shared_from_this(this); } u32 get_id() const { return idm_id; } }; @@ -342,7 +344,7 @@ public: // Utilities u32 get_id() const { return idm_id; } - shared_ptr get_shared_ptr() const { return idm::get_unlocked(idm_id); } + shared_ptr get_shared_ptr() const { return stx::make_shared_from_this(this); } }; /* diff --git a/rpcs3/util/shared_ptr.hpp b/rpcs3/util/shared_ptr.hpp index fb3c2c4019..e9bdf83b3b 100644 --- a/rpcs3/util/shared_ptr.hpp +++ b/rpcs3/util/shared_ptr.hpp @@ -361,13 +361,8 @@ namespace stx [[deprecated("Use null_ptr")]] shared_ptr(std::nullptr_t) = delete; // Not-so-aliasing constructor: emulates std::enable_shared_from_this without its overhead - explicit shared_ptr(T* _this) noexcept - : m_ptr(_this) - { - // Random checks which may fail on invalid pointer - ensure((reinterpret_cast(d()->destroy) - 0x10000) >> 47 == 0); - ensure((d()->refs++ - 1) >> 58 == 0); - } + template + friend shared_ptr make_shared_from_this(const Type* _this) noexcept; template requires same_ptr_implicit_v shared_ptr(const shared_ptr& r) noexcept @@ -562,11 +557,29 @@ namespace stx template requires (std::is_constructible_v, T&&>) - static shared_ptr> make_shared_value(T&& value) + static shared_ptr> make_shared_value(T&& value) noexcept { return make_single_value(std::forward(value)); } + // Not-so-aliasing constructor: emulates std::enable_shared_from_this without its overhead + template + static shared_ptr make_shared_from_this(const T* _this) noexcept + { + shared_ptr r; + r.m_ptr = const_cast(_this); + + if (!_this) [[unlikely]] + { + return r; + } + + // Random checks which may fail on invalid pointer + ensure((reinterpret_cast(r.d()->destroy.load()) - 0x10000) >> 47 == 0); + ensure((r.d()->refs++ - 1) >> 58 == 0); + return r; + } + // Atomic simplified shared pointer template class atomic_ptr @@ -1059,9 +1072,9 @@ namespace stx do { // Update old head with current value - next.m_ptr = reinterpret_cast(old.m_val.raw() >> c_ref_size); + next.m_ptr = std::launder(ptr_to(old.m_val.raw())); - } while (!m_val.compare_exchange(old.m_val.raw(), reinterpret_cast(exch.m_ptr) << c_ref_size)); + } while (!m_val.compare_exchange(old.m_val.raw(), to_val(exch.m_ptr))); // This argument is consumed (moved from) exch.m_ptr = nullptr; @@ -1076,7 +1089,7 @@ namespace stx // Simple atomic load is much more effective than load(), but it's a non-owning reference T* observe() const noexcept { - return reinterpret_cast(m_val >> c_ref_size); + return std::launder(ptr_to(m_val)); } explicit constexpr operator bool() const noexcept @@ -1138,11 +1151,6 @@ namespace stx return false; } - constexpr std::nullptr_t get() const noexcept - { - return nullptr; - } - } null_ptr; }