mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-04 22:11:26 +12:00
shared_ptr.hpp: improve atomic_ptr methods
This commit is contained in:
parent
c2a85bde08
commit
332410d20b
1 changed files with 70 additions and 22 deletions
|
@ -600,13 +600,13 @@ namespace stx
|
||||||
|
|
||||||
constexpr atomic_ptr() noexcept = default;
|
constexpr atomic_ptr() noexcept = default;
|
||||||
|
|
||||||
constexpr atomic_ptr(std::nullptr_t) noexcept {}
|
// Optimized value construct
|
||||||
|
template <typename... Args, typename = std::enable_if_t<std::is_constructible_v<T, Args...>>>
|
||||||
explicit atomic_ptr(T value) noexcept
|
explicit atomic_ptr(Args&&... args) noexcept
|
||||||
{
|
{
|
||||||
auto r = make_single<T>(std::move(value));
|
shared_type r = make_single<T>(std::forward<Args>(args)...);
|
||||||
m_val = reinterpret_cast<uptr>(std::exchange(r.m_ptr, nullptr)) << c_ref_size;
|
m_val = reinterpret_cast<uptr>(std::exchange(r.m_ptr, nullptr)) << c_ref_size;
|
||||||
d()->refs += c_ref_mask;
|
d()->refs.raw() += c_ref_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U, typename = std::enable_if_t<is_same_ptr_cast_v<T, U>>>
|
template <typename U, typename = std::enable_if_t<is_same_ptr_cast_v<T, U>>>
|
||||||
|
@ -653,10 +653,14 @@ namespace stx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
atomic_ptr& operator=(T value) noexcept
|
// Optimized value assignment
|
||||||
|
atomic_ptr& operator=(std::remove_cv_t<T> value) noexcept
|
||||||
{
|
{
|
||||||
// TODO: does it make sense?
|
shared_type r = make_single<T>(std::move(value));
|
||||||
store(make_single<T>(std::move(value)));
|
r.d()->refs += c_ref_mask;
|
||||||
|
|
||||||
|
atomic_ptr old;
|
||||||
|
old.m_val.raw() = m_val.exchange(reinterpret_cast<uptr>(std::exchange(r.m_ptr, nullptr)) << c_ref_size);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,9 +729,19 @@ namespace stx
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void store(T value) noexcept
|
operator shared_type() const noexcept
|
||||||
{
|
{
|
||||||
store(make_single<T>(std::move(value)));
|
return load();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args, typename = std::enable_if_t<std::is_constructible_v<T, Args...>>>
|
||||||
|
void store(Args&&... args) noexcept
|
||||||
|
{
|
||||||
|
shared_type r = make_single<T>(std::forward<Args>(args)...);
|
||||||
|
r.d()->refs.raw() += c_ref_mask;
|
||||||
|
|
||||||
|
atomic_ptr old;
|
||||||
|
old.m_val.raw() = m_val.exchange(reinterpret_cast<uptr>(std::exchange(r.m_ptr, nullptr)) << c_ref_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void store(shared_type value) noexcept
|
void store(shared_type value) noexcept
|
||||||
|
@ -742,6 +756,20 @@ namespace stx
|
||||||
old.m_val.raw() = m_val.exchange(reinterpret_cast<uptr>(std::exchange(value.m_ptr, nullptr)) << c_ref_size);
|
old.m_val.raw() = m_val.exchange(reinterpret_cast<uptr>(std::exchange(value.m_ptr, nullptr)) << c_ref_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename... Args, typename = std::enable_if_t<std::is_constructible_v<T, Args...>>>
|
||||||
|
[[nodiscard]] shared_type exchange(Args&&... args) noexcept
|
||||||
|
{
|
||||||
|
shared_type r = make_single<T>(std::forward<Args>(args)...);
|
||||||
|
r.d()->refs.raw() += c_ref_mask;
|
||||||
|
|
||||||
|
atomic_ptr old;
|
||||||
|
old.m_val.raw() += m_val.exchange(reinterpret_cast<uptr>(r.m_ptr) << c_ref_size);
|
||||||
|
old.m_val.raw() += 1;
|
||||||
|
|
||||||
|
r.m_ptr = std::launder(reinterpret_cast<element_type*>(old.m_val >> c_ref_size));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] shared_type exchange(shared_type value) noexcept
|
[[nodiscard]] shared_type exchange(shared_type value) noexcept
|
||||||
{
|
{
|
||||||
if (value.m_ptr)
|
if (value.m_ptr)
|
||||||
|
@ -751,19 +779,37 @@ namespace stx
|
||||||
}
|
}
|
||||||
|
|
||||||
atomic_ptr old;
|
atomic_ptr old;
|
||||||
old.m_val.raw() += m_val.exchange(reinterpret_cast<uptr>(std::exchange(value.m_ptr, nullptr)) << c_ref_size);
|
old.m_val.raw() += m_val.exchange(reinterpret_cast<uptr>(value.m_ptr) << c_ref_size);
|
||||||
|
old.m_val.raw() += 1;
|
||||||
|
|
||||||
shared_type r;
|
value.m_ptr = std::launder(reinterpret_cast<element_type*>(old.m_val >> c_ref_size));
|
||||||
r.m_ptr = std::launder(reinterpret_cast<element_type*>(old.m_val >> c_ref_size));
|
return value;
|
||||||
|
|
||||||
if (old.m_val.raw())
|
|
||||||
{
|
|
||||||
old.m_val.raw()++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bool compare_exchange(shared_type& cmp_and_old, shared_type exch)
|
||||||
|
// {
|
||||||
|
// }
|
||||||
|
|
||||||
|
// template <typename U, typename = std::enable_if_t<is_same_ptr_cast_v<T, U>>>
|
||||||
|
// shared_type compare_and_swap(const shared_ptr<U>& cmp, shared_type exch)
|
||||||
|
// {
|
||||||
|
// }
|
||||||
|
|
||||||
|
// template <typename U, typename = std::enable_if_t<is_same_ptr_cast_v<T, U>>>
|
||||||
|
// bool compare_and_swap_test(const shared_ptr<U>& cmp, shared_type exch)
|
||||||
|
// {
|
||||||
|
// }
|
||||||
|
|
||||||
|
// template <typename U, typename = std::enable_if_t<is_same_ptr_cast_v<T, U>>>
|
||||||
|
// shared_type compare_and_swap(const single_ptr<U>& cmp, shared_type exch)
|
||||||
|
// {
|
||||||
|
// }
|
||||||
|
|
||||||
|
// template <typename U, typename = std::enable_if_t<is_same_ptr_cast_v<T, U>>>
|
||||||
|
// bool compare_and_swap_test(const single_ptr<U>& cmp, shared_type exch)
|
||||||
|
// {
|
||||||
|
// }
|
||||||
|
|
||||||
// Simple atomic load is much more effective than load(), but it's a non-owning reference
|
// Simple atomic load is much more effective than load(), but it's a non-owning reference
|
||||||
const volatile void* observe() const noexcept
|
const volatile void* observe() const noexcept
|
||||||
{
|
{
|
||||||
|
@ -775,12 +821,14 @@ namespace stx
|
||||||
return m_val != 0;
|
return m_val != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_equal(const shared_ptr<T>& r) const noexcept
|
template <typename U, typename = std::enable_if_t<is_same_ptr_cast_v<T, U>>>
|
||||||
|
bool is_equal(const shared_ptr<U>& r) const noexcept
|
||||||
{
|
{
|
||||||
return observe() == r.get();
|
return observe() == r.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_equal(const single_ptr<T>& r) const noexcept
|
template <typename U, typename = std::enable_if_t<is_same_ptr_cast_v<T, U>>>
|
||||||
|
bool is_equal(const single_ptr<U>& r) const noexcept
|
||||||
{
|
{
|
||||||
return observe() == r.get();
|
return observe() == r.get();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue