diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index 88ff7e2991..e2c2198bdc 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -566,9 +566,41 @@ void fmt_class_string::format(std::string& out, u64 arg) fmt::append(out, "\n(in file %s", loc.file_name()); } - if (auto func = loc.function_name(); func && func[0]) + if (std::string_view full_func{loc.function_name() ? loc.function_name() : ""}; !full_func.empty()) { - fmt::append(out, ", in function %s)", func); + // Remove useless disambiguators + std::string func = fmt::replace_all(std::string(full_func), { + {"struct ", ""}, + {"class ", ""}, + {"enum ", ""}, + {"typename ", ""}, +#ifdef _MSC_VER + {"__cdecl ", ""}, +#endif + {"unsigned long long", "ullong"}, + //{"unsigned long", "ulong"}, // ullong + {"unsigned int", "uint"}, + {"unsigned short", "ushort"}, + {"unsigned char", "uchar"}}); + + // Remove function argument signature for long names + for (usz index = func.find_first_of('('); index != umax && func.size() >= 100u; index = func.find_first_of('(', index)) + { + // Operator() function + if (func.compare(0, 3, "()("sv) == 0 || func.compare(0, 3, "() "sv)) + { + if (usz not_space = func.find_first_not_of(' ', index + 2); not_space != umax && func[not_space] == '(') + { + index += 2; + continue; + } + } + + func = func.substr(0, index); + break; + } + + fmt::append(out, ", in function '%s')", func); } else { diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index a7f7165163..c31a0b804f 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -2555,13 +2555,13 @@ std::string thread_ctrl::get_name_cached() return *name_cache; } -thread_base::thread_base(native_entry entry, std::string name) +thread_base::thread_base(native_entry entry, std::string name) noexcept : entry_point(entry) , m_tname(make_single_value(std::move(name))) { } -thread_base::~thread_base() +thread_base::~thread_base() noexcept { // Cleanup abandoned tasks: initialize default results and signal this->exec(); @@ -2602,7 +2602,7 @@ bool thread_base::join(bool dtor) const if (i >= 16 && !(i & (i - 1)) && timeout != atomic_wait_timeout::inf) { - sig_log.error(u8"Thread [%s] is too sleepy. Waiting for it %.3fus already!", *m_tname.load(), (utils::get_tsc() - stamp0) / (utils::get_tsc_freq() / 1000000.)); + sig_log.error("Thread [%s] is too sleepy. Waiting for it %.3fus already!", *m_tname.load(), (utils::get_tsc() - stamp0) / (utils::get_tsc_freq() / 1000000.)); } } diff --git a/Utilities/Thread.h b/Utilities/Thread.h index 7f2e0b522f..4350915d70 100644 --- a/Utilities/Thread.h +++ b/Utilities/Thread.h @@ -172,9 +172,9 @@ private: friend class named_thread; protected: - thread_base(native_entry, std::string name); + thread_base(native_entry, std::string name) noexcept; - ~thread_base(); + ~thread_base() noexcept; public: // Get CPU cycles since last time this function was called. First call returns 0. @@ -351,7 +351,7 @@ public: // Sets the native thread priority and returns it to zero at destructor struct scoped_priority { - explicit scoped_priority(int prio) + explicit scoped_priority(int prio) noexcept { set_native_priority(prio); } @@ -360,7 +360,7 @@ public: scoped_priority& operator=(const scoped_priority&) = delete; - ~scoped_priority() + ~scoped_priority() noexcept { set_native_priority(0); } @@ -388,7 +388,7 @@ class thread_future_t : public thread_future, result_storage(args)...) , m_func(std::forward(func)) { @@ -417,7 +417,7 @@ public: }; } - ~thread_future_t() + ~thread_future_t() noexcept { if constexpr (!future::empty && !Discard) { @@ -570,7 +570,7 @@ public: named_thread& operator=(const named_thread&) = delete; // Wait for the completion and access result (if not void) - [[nodiscard]] decltype(auto) operator()() + [[nodiscard]] decltype(auto) operator()() noexcept { thread::join(); @@ -581,7 +581,7 @@ public: } // Wait for the completion and access result (if not void) - [[nodiscard]] decltype(auto) operator()() const + [[nodiscard]] decltype(auto) operator()() const noexcept { thread::join(); @@ -593,7 +593,7 @@ public: // Send command to the thread to invoke directly (references should be passed via std::ref()) template - auto operator()(Arg&& arg, Args&&... args) + auto operator()(Arg&& arg, Args&&... args) noexcept { // Overloaded operator() of the Context. constexpr bool v1 = std::is_invocable_v; @@ -667,12 +667,12 @@ public: } // Access thread state - operator thread_state() const + operator thread_state() const noexcept { return static_cast(thread::m_sync.load() & 3); } - named_thread& operator=(thread_state s) + named_thread& operator=(thread_state s) noexcept { if (s == thread_state::created) { @@ -693,7 +693,7 @@ public: if constexpr (std::is_assignable_v) { - static_cast(*this) = s; + static_cast(*this) = thread_state::aborting; } if (notify_sync) @@ -706,13 +706,18 @@ public: { // This participates in emulation stopping, use destruction-alike semantics thread::join(true); + + if constexpr (std::is_assignable_v) + { + static_cast(*this) = thread_state::finished; + } } return *this; } // Context type doesn't need virtual destructor - ~named_thread() + ~named_thread() noexcept { // Assign aborting state forcefully and join thread operator=(thread_state::finished); diff --git a/rpcs3/Emu/Cell/lv2/sys_config.cpp b/rpcs3/Emu/Cell/lv2/sys_config.cpp index 8194fb222b..c39444ccd0 100644 --- a/rpcs3/Emu/Cell/lv2/sys_config.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_config.cpp @@ -109,10 +109,29 @@ void lv2_config::add_service_event(shared_ptr event) void lv2_config::remove_service_event(u32 id) { + shared_ptr ptr; + std::lock_guard lock(m_mutex); - events.erase(id); + + if (auto it = events.find(id); it != events.end()) + { + ptr = std::move(it->second); + events.erase(it); + } } +lv2_config_service_event& lv2_config_service_event::operator=(thread_state s) noexcept +{ + if (s == thread_state::finished) + { + if (auto global = g_fxo->try_get()) + { + global->remove_service_event(id); + } + } + + return *this; +} // 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 337ffbe74f..3915dfc8cb 100644 --- a/rpcs3/Emu/Cell/lv2/sys_config.h +++ b/rpcs3/Emu/Cell/lv2/sys_config.h @@ -390,13 +390,9 @@ public: } // Destructor - ~lv2_config_service_event() noexcept - { - if (auto global = g_fxo->try_get()) - { - global->remove_service_event(id); - } - } + lv2_config_service_event& operator=(thread_state s) noexcept; + + ~lv2_config_service_event() noexcept = default; // Notify queue that this event exists bool notify() const; diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.cpp b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.cpp index 011bc4e8f8..0e1543157c 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.cpp @@ -175,3 +175,14 @@ void lv2_socket::queue_wake(ppu_thread* ppu) break; } } + +lv2_socket& lv2_socket::operator=(thread_state s) noexcept +{ + if (s == thread_state::finished) + { + close(); + } + + return *this; +} + diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.h b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.h index 4cbab143dc..4703f31d5f 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.h +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket.h @@ -27,6 +27,8 @@ using socket_type = uptr; using socket_type = int; #endif +enum class thread_state : u32; + class lv2_socket { public: @@ -62,7 +64,8 @@ public: lv2_socket(utils::serial&, lv2_socket_type type); static std::function load(utils::serial& ar); void save(utils::serial&, bool save_only_this_class = false); - virtual ~lv2_socket() = default; + ~lv2_socket() noexcept = default; + lv2_socket& operator=(thread_state s) noexcept; std::unique_lock lock(); diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.cpp b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.cpp index b8398480cb..75fd375e5a 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.cpp @@ -57,19 +57,6 @@ void lv2_socket_native::save(utils::serial& ar) ar(is_socket_connected()); } -lv2_socket_native::~lv2_socket_native() -{ - std::lock_guard lock(mutex); - if (socket) - { -#ifdef _WIN32 - ::closesocket(socket); -#else - ::close(socket); -#endif - } -} - s32 lv2_socket_native::create_socket() { ensure(family == SYS_NET_AF_INET); @@ -1114,10 +1101,12 @@ void lv2_socket_native::close() socket = {}; } - auto& dnshook = g_fxo->get(); - dnshook.remove_dns_spy(lv2_id); + if (auto dnshook = g_fxo->try_get()) + { + dnshook->remove_dns_spy(lv2_id); + } - if (bound_port) + if (bound_port && g_fxo->is_init>()) { auto& nph = g_fxo->get>(); nph.upnp_remove_port_mapping(bound_port, type == SYS_NET_SOCK_STREAM ? "TCP" : "UDP"); diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.h b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.h index 08a1f4575a..e9a2b21bb6 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.h +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_native.h @@ -35,7 +35,6 @@ public: lv2_socket_native(lv2_socket_family family, lv2_socket_type type, lv2_ip_protocol protocol); lv2_socket_native(utils::serial& ar, lv2_socket_type type); void save(utils::serial& ar); - ~lv2_socket_native(); s32 create_socket(); std::tuple, sys_net_sockaddr> accept(bool is_lock = true) override; diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.cpp b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.cpp index a4228a0322..8614d37205 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2p.cpp @@ -330,8 +330,9 @@ void lv2_socket_p2p::close() return; } - auto& nc = g_fxo->get(); + if (g_fxo->is_init()) { + auto& nc = g_fxo->get(); std::lock_guard lock(nc.list_p2p_ports_mutex); if (!nc.list_p2p_ports.contains(port)) diff --git a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.cpp b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.cpp index a363301dc2..d6c98b670a 100644 --- a/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_net/lv2_socket_p2ps.cpp @@ -944,8 +944,9 @@ void lv2_socket_p2ps::close() return; } - auto& nc = g_fxo->get(); + if (g_fxo->is_init()) { + auto& nc = g_fxo->get(); std::lock_guard lock(nc.list_p2p_ports_mutex); auto& p2p_port = ::at32(nc.list_p2p_ports, port); { @@ -973,8 +974,10 @@ void lv2_socket_p2ps::close() } } - auto& tcpm = g_fxo->get>(); - tcpm.clear_all_messages(lv2_id); + if (const auto tcpm = g_fxo->try_get>()) + { + tcpm->clear_all_messages(lv2_id); + } } s32 lv2_socket_p2ps::shutdown([[maybe_unused]] s32 how) diff --git a/rpcs3/Emu/Cell/lv2/sys_process.cpp b/rpcs3/Emu/Cell/lv2/sys_process.cpp index cfe0859569..8038ffc248 100644 --- a/rpcs3/Emu/Cell/lv2/sys_process.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_process.cpp @@ -434,9 +434,12 @@ void lv2_exitspawn(ppu_thread& ppu, std::vector& argv, std::vector< using namespace id_manager; shared_ptr idm_capture = make_shared(); + + if (!is_real_reboot) { - reader_lock rlock{g_mutex}; + reader_lock rlock{id_manager::g_mutex}; g_fxo->get>().save(*idm_capture); + stx::serial_breathe_and_tag(*idm_capture, "id_map", false); } idm_capture->set_reading_state(); diff --git a/rpcs3/Emu/GDB.cpp b/rpcs3/Emu/GDB.cpp index d61f558cb6..56ad52705a 100644 --- a/rpcs3/Emu/GDB.cpp +++ b/rpcs3/Emu/GDB.cpp @@ -587,7 +587,7 @@ bool gdb_thread::cmd_thread_info(gdb_cmd&) bool gdb_thread::cmd_current_thread(gdb_cmd&) { - return send_cmd_ack(selected_thread && selected_thread->state.none_of(cpu_flag::exit) ? "" : ("QC" + u64_to_padded_hex(selected_thread->id))); + return send_cmd_ack(selected_thread && selected_thread->state.none_of(cpu_flag::exit) ? ("QC" + u64_to_padded_hex(selected_thread->id)) : ""); } bool gdb_thread::cmd_read_register(gdb_cmd& cmd) @@ -733,7 +733,7 @@ bool gdb_thread::cmd_read_all_registers(gdb_cmd&) return send_cmd_ack(result); } - GDB.warning("Unimplemented thread type %d.", selected_thread ->id_type()); + GDB.warning("Unimplemented thread type %d.", selected_thread->id_type()); return send_cmd_ack(""); } diff --git a/rpcs3/Emu/IdManager.h b/rpcs3/Emu/IdManager.h index bf128a393f..b555907d13 100644 --- a/rpcs3/Emu/IdManager.h +++ b/rpcs3/Emu/IdManager.h @@ -801,6 +801,15 @@ public: } } + if constexpr (std::is_assignable_v) + { + if (ptr) + { + constexpr thread_state finished{3}; + *static_cast(ptr.get()) = finished; + } + } + return true; } @@ -824,6 +833,15 @@ public: } } + if constexpr (std::is_assignable_v) + { + if (ptr) + { + constexpr thread_state finished{3}; + *static_cast(ptr.get()) = finished; + } + } + return true; } diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index e67cb1bd6e..551e7de36d 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -2718,8 +2718,15 @@ bool Emulator::Pause(bool freeze_emulation, bool show_resume_message) cpu.state += cpu_flag::dbg_global_pause; }; - idm::select>(on_select); - idm::select>(on_select); + if (g_fxo->is_init>>()) + { + idm::select>(on_select); + } + + if (g_fxo->is_init>>()) + { + idm::select>(on_select); + } if (auto rsx = g_fxo->try_get()) { @@ -2760,6 +2767,7 @@ bool Emulator::Pause(bool freeze_emulation, bool show_resume_message) std::unique_ptr> m_thread; }; + g_fxo->need(); g_fxo->get().m_thread.reset(); g_fxo->get().m_thread = std::make_unique>("Pause Message Thread"sv, std::move(refresh_l)); }); diff --git a/rpcs3/Emu/savestate_utils.cpp b/rpcs3/Emu/savestate_utils.cpp index 487eab5b07..790da3b035 100644 --- a/rpcs3/Emu/savestate_utils.cpp +++ b/rpcs3/Emu/savestate_utils.cpp @@ -372,6 +372,7 @@ namespace stx { // Reset, probably a new utils::serial object s_tls_call_count = 1; + s_tls_object_name = "none"sv; } s_tls_current_pos = ar.pos; diff --git a/rpcs3/rpcs3qt/debugger_frame.cpp b/rpcs3/rpcs3qt/debugger_frame.cpp index bdddada077..56b1ccb0a4 100644 --- a/rpcs3/rpcs3qt/debugger_frame.cpp +++ b/rpcs3/rpcs3qt/debugger_frame.cpp @@ -1049,8 +1049,15 @@ void debugger_frame::UpdateUnitList() if (emu_state != system_state::stopped) { - idm::select>(on_select, idm::unlocked); - idm::select>(on_select, idm::unlocked); + if (g_fxo->is_init>>()) + { + idm::select>(on_select, idm::unlocked); + } + + if (g_fxo->is_init>>()) + { + idm::select>(on_select, idm::unlocked); + } if (const auto render = g_fxo->try_get(); render && render->ctrl) { diff --git a/rpcs3/util/shared_ptr.hpp b/rpcs3/util/shared_ptr.hpp index 6e07db68fd..7685cfda91 100644 --- a/rpcs3/util/shared_ptr.hpp +++ b/rpcs3/util/shared_ptr.hpp @@ -154,6 +154,7 @@ namespace stx if (m_ptr) [[likely]] { const auto o = d(); + ensure(o->refs == 1); o->destroy.load()(o); m_ptr = nullptr; } @@ -437,11 +438,15 @@ namespace stx // Set to null void reset() noexcept { - const auto o = d(); - - if (m_ptr && !--o->refs) [[unlikely]] + if (m_ptr) [[unlikely]] { - o->destroy(o); + const auto o = d(); + + if (!--o->refs) + { + o->destroy(o); + } + m_ptr = nullptr; } } @@ -571,7 +576,7 @@ namespace stx { mutable atomic_t m_val{0}; - static shared_counter* d(uptr val) + static shared_counter* d(uptr val) noexcept { return std::launder(reinterpret_cast((val >> c_ref_size) - sizeof(shared_counter))); } @@ -581,9 +586,32 @@ namespace stx return d(m_val); } + static uptr to_val(const volatile std::remove_extent_t* ptr) noexcept + { + return (reinterpret_cast(ptr) << c_ref_size); + } + + static std::remove_extent_t* ptr_to(uptr val) noexcept + { + return reinterpret_cast*>(val >> c_ref_size); + } + template friend class atomic_ptr; + // Helper struct to check if a type is an instance of a template + template class Template> + struct is_instance_of : std::false_type {}; + + template class Template> + struct is_instance_of, Template> : std::true_type {}; + + template + static constexpr bool is_stx_pointer = false + || is_instance_of, shared_ptr>::value + || is_instance_of, single_ptr>::value + || is_instance_of, atomic_ptr>::value; + public: using element_type = std::remove_extent_t; @@ -592,11 +620,14 @@ namespace stx constexpr atomic_ptr() noexcept = default; // Optimized value construct - template requires (!(sizeof...(Args) == 1 && (std::is_same_v, shared_type> || ...)) && std::is_constructible_v) + template requires (true + && sizeof...(Args) != 0 + && !(sizeof...(Args) == 1 && (is_stx_pointer || ...)) + && std::is_constructible_v) explicit atomic_ptr(Args&&... args) noexcept { shared_type r = make_single(std::forward(args)...); - m_val = reinterpret_cast(std::exchange(r.m_ptr, nullptr)) << c_ref_size; + m_val.raw() = to_val(std::exchange(r.m_ptr, nullptr)); d()->refs.raw() += c_ref_mask; } @@ -604,32 +635,38 @@ namespace stx atomic_ptr(const shared_ptr& r) noexcept { // Obtain a ref + as many refs as an atomic_ptr can additionally reference - m_val = reinterpret_cast(r.m_ptr) << c_ref_size; - if (m_val) - d()->refs += c_ref_mask + 1; + if (uptr rval = to_val(r.m_ptr)) + { + m_val.raw() = rval; + d(rval)->refs += c_ref_mask + 1; + } } template requires same_ptr_implicit_v atomic_ptr(shared_ptr&& r) noexcept { - m_val = reinterpret_cast(r.m_ptr) << c_ref_size; - r.m_ptr = nullptr; + if (uptr rval = to_val(r.m_ptr)) + { + m_val.raw() = rval; + d(rval)->refs += c_ref_mask; + } - if (m_val) - d()->refs += c_ref_mask; + r.m_ptr = nullptr; } template requires same_ptr_implicit_v atomic_ptr(single_ptr&& r) noexcept { - m_val = reinterpret_cast(r.m_ptr) << c_ref_size; - r.m_ptr = nullptr; + if (uptr rval = to_val(r.m_ptr)) + { + m_val.raw() = rval; + d(rval)->refs += c_ref_mask; + } - if (m_val) - d()->refs += c_ref_mask; + r.m_ptr = nullptr; } - ~atomic_ptr() + ~atomic_ptr() noexcept { const uptr v = m_val.raw(); @@ -645,13 +682,13 @@ namespace stx } // Optimized value assignment - atomic_ptr& operator=(std::remove_cv_t value) noexcept + atomic_ptr& operator=(std::remove_cv_t value) noexcept requires (!is_stx_pointer) { shared_type r = make_single(std::move(value)); r.d()->refs.raw() += c_ref_mask; atomic_ptr old; - old.m_val.raw() = m_val.exchange(reinterpret_cast(std::exchange(r.m_ptr, nullptr)) << c_ref_size); + old.m_val.raw() = m_val.exchange(to_val(std::exchange(r.m_ptr, nullptr))); return *this; } @@ -704,7 +741,7 @@ namespace stx } // Set referenced pointer - r.m_ptr = std::launder(reinterpret_cast(prev >> c_ref_size)); + r.m_ptr = std::launder(ptr_to(prev)); r.d()->refs++; // Dereference if still the same pointer @@ -749,7 +786,7 @@ namespace stx // Set fake unreferenced pointer if (did_ref) { - r.m_ptr = std::launder(reinterpret_cast(prev >> c_ref_size)); + r.m_ptr = std::launder(ptr_to(prev)); } // Result temp storage @@ -805,14 +842,17 @@ namespace stx // Create an object from variadic args // If a type needs shared_type to be constructed, std::reference_wrapper can be used - template requires (!(sizeof...(Args) == 1 && (std::is_same_v, shared_type> || ...)) && std::is_constructible_v) + template requires (true + && sizeof...(Args) != 0 + && !(sizeof...(Args) == 1 && (is_stx_pointer || ...)) + && std::is_constructible_v) void store(Args&&... args) noexcept { shared_type r = make_single(std::forward(args)...); r.d()->refs.raw() += c_ref_mask; atomic_ptr old; - old.m_val.raw() = m_val.exchange(reinterpret_cast(std::exchange(r.m_ptr, nullptr)) << c_ref_size); + old.m_val.raw() = m_val.exchange(to_val(std::exchange(r.m_ptr, nullptr))); } void store(shared_type value) noexcept @@ -824,20 +864,23 @@ namespace stx } atomic_ptr old; - old.m_val.raw() = m_val.exchange(reinterpret_cast(std::exchange(value.m_ptr, nullptr)) << c_ref_size); + old.m_val.raw() = m_val.exchange(to_val(std::exchange(value.m_ptr, nullptr))); } - template requires (!(sizeof...(Args) == 1 && (std::is_same_v, shared_type> || ...)) && std::is_constructible_v) + template requires (true + && sizeof...(Args) != 0 + && !(sizeof...(Args) == 1 && (is_stx_pointer || ...)) + && std::is_constructible_v) [[nodiscard]] shared_type exchange(Args&&... args) noexcept { shared_type r = make_single(std::forward(args)...); r.d()->refs.raw() += c_ref_mask; atomic_ptr old; - old.m_val.raw() += m_val.exchange(reinterpret_cast(r.m_ptr) << c_ref_size); + old.m_val.raw() = m_val.exchange(to_val(r.m_ptr)); old.m_val.raw() += 1; - r.m_ptr = std::launder(reinterpret_cast(old.m_val >> c_ref_size)); + r.m_ptr = std::launder(ptr_to(old.m_val)); return r; } @@ -850,10 +893,10 @@ namespace stx } atomic_ptr old; - old.m_val.raw() += m_val.exchange(reinterpret_cast(value.m_ptr) << c_ref_size); + old.m_val.raw() = m_val.exchange(to_val(value.m_ptr)); old.m_val.raw() += 1; - value.m_ptr = std::launder(reinterpret_cast(old.m_val >> c_ref_size)); + value.m_ptr = std::launder(ptr_to(old.m_val)); return value; } @@ -898,10 +941,10 @@ namespace stx } atomic_ptr old_exch; - old_exch.m_val.raw() = reinterpret_cast(std::exchange(exch.m_ptr, nullptr)) << c_ref_size; + old_exch.m_val.raw() = to_val(std::exchange(exch.m_ptr, nullptr)); // Set to reset old cmp_and_old value - old.m_val.raw() = (reinterpret_cast(cmp_and_old.m_ptr) << c_ref_size) | c_ref_mask; + old.m_val.raw() = to_val(cmp_and_old.m_ptr) | c_ref_mask; if (!_val) { @@ -909,7 +952,7 @@ namespace stx } // Set referenced pointer - cmp_and_old.m_ptr = std::launder(reinterpret_cast(_val >> c_ref_size)); + cmp_and_old.m_ptr = std::launder(ptr_to(_val)); cmp_and_old.d()->refs++; // Dereference if still the same pointer @@ -977,7 +1020,7 @@ namespace stx } // Failure (return references) - old.m_val.raw() = reinterpret_cast(std::exchange(exch.m_ptr, nullptr)) << c_ref_size; + old.m_val.raw() = to_val(std::exchange(exch.m_ptr, nullptr)); return false; }