mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-10-03 14:50:18 +00:00
shared_ptr.hpp: further fixes
Improved is_same_ptr() trait (added third "maybe" category). Fallback to pseudo-runtime check in certain cases (if "maybe"). Fix single_ptr moving assignment operator.
This commit is contained in:
parent
332c512eed
commit
8c5f2b249c
2 changed files with 124 additions and 53 deletions
|
@ -25,16 +25,23 @@ namespace stx
|
||||||
static thread_local const
|
static thread_local const
|
||||||
#endif
|
#endif
|
||||||
fake_t<std::remove_cv_t<T>> sample{};
|
fake_t<std::remove_cv_t<T>> sample{};
|
||||||
|
|
||||||
|
template <typename From, typename To, typename = void>
|
||||||
|
struct can_static_cast : std::false_type {};
|
||||||
|
|
||||||
|
template <typename From, typename To>
|
||||||
|
struct can_static_cast<From, To, std::void_t<decltype(static_cast<To>(std::declval<From>()))>> : std::true_type {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Classify compile-time information available for pointers
|
||||||
|
enum class same_ptr
|
||||||
|
{
|
||||||
|
no,
|
||||||
|
yes,
|
||||||
|
maybe
|
||||||
|
};
|
||||||
|
|
||||||
template <typename X, typename Y>
|
template <typename X, typename Y>
|
||||||
constexpr bool is_same_ptr_test(const volatile Y*, ...)
|
|
||||||
{
|
|
||||||
// Can't sample abstract class
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename X, typename Y, std::enable_if_t<!std::is_abstract_v<Y>, int> = 0>
|
|
||||||
constexpr bool is_same_ptr_test(const volatile Y* ptr = std::addressof(detail::sample<Y>.data))
|
constexpr bool is_same_ptr_test(const volatile Y* ptr = std::addressof(detail::sample<Y>.data))
|
||||||
{
|
{
|
||||||
return static_cast<const volatile X*>(ptr) == static_cast<const volatile void*>(ptr);
|
return static_cast<const volatile X*>(ptr) == static_cast<const volatile void*>(ptr);
|
||||||
|
@ -42,26 +49,26 @@ namespace stx
|
||||||
|
|
||||||
// Checks whether the cast between two types is the same pointer
|
// Checks whether the cast between two types is the same pointer
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
constexpr bool is_same_ptr() noexcept
|
constexpr same_ptr is_same_ptr() noexcept
|
||||||
{
|
{
|
||||||
if constexpr (std::is_void_v<T> || std::is_void_v<U> || std::is_same_v<T, U>)
|
if constexpr (std::is_void_v<T> || std::is_void_v<U> || std::is_same_v<std::remove_cv_t<T>, std::remove_cv_t<U>>)
|
||||||
{
|
{
|
||||||
return true;
|
return same_ptr::yes;
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_convertible_v<U*, T*>)
|
else if constexpr (detail::can_static_cast<U*, T*>::value && !std::is_abstract_v<U>)
|
||||||
{
|
{
|
||||||
return is_same_ptr_test<T, U>();
|
return is_same_ptr_test<T, U>() ? same_ptr::yes : same_ptr::no;
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_convertible_v<T*, U*>)
|
else if constexpr (detail::can_static_cast<T*, U*>::value && !std::is_abstract_v<T>)
|
||||||
{
|
{
|
||||||
return is_same_ptr_test<U, T>();
|
return is_same_ptr_test<U, T>() ? same_ptr::yes : same_ptr::no;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !std::is_class_v<T> && !std::is_class_v<U> && !std::is_union_v<T> && !std::is_union_v<U>;
|
return same_ptr::maybe;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
constexpr bool is_same_ptr_cast_v = std::is_convertible_v<U*, T*> && is_same_ptr<T, U>();
|
constexpr same_ptr is_same_ptr_cast_v = std::is_convertible_v<U*, T*> ? is_same_ptr<T, U>() : same_ptr::no;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class single_ptr;
|
class single_ptr;
|
||||||
|
@ -166,10 +173,13 @@ namespace stx
|
||||||
r.m_ptr = nullptr;
|
r.m_ptr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
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> != same_ptr::no>>
|
||||||
single_ptr(single_ptr<U>&& r) noexcept
|
single_ptr(single_ptr<U>&& r) noexcept
|
||||||
: m_ptr(r.m_ptr)
|
|
||||||
{
|
{
|
||||||
|
if constexpr (is_same_ptr<T, U>() == same_ptr::maybe)
|
||||||
|
ensure(is_same_ptr_test<T, U>(r.m_ptr));
|
||||||
|
|
||||||
|
m_ptr = r.m_ptr;
|
||||||
r.m_ptr = nullptr;
|
r.m_ptr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,16 +192,17 @@ namespace stx
|
||||||
|
|
||||||
single_ptr& operator=(single_ptr&& r) noexcept
|
single_ptr& operator=(single_ptr&& r) noexcept
|
||||||
{
|
{
|
||||||
m_ptr = r.m_ptr;
|
single_ptr(std::move(r)).swap(*this);
|
||||||
r.m_ptr = nullptr;
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
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> != same_ptr::no>>
|
||||||
single_ptr& operator=(single_ptr<U>&& r) noexcept
|
single_ptr& operator=(single_ptr<U>&& r) noexcept
|
||||||
{
|
{
|
||||||
m_ptr = r.m_ptr;
|
if constexpr (is_same_ptr<T, U>() == same_ptr::maybe)
|
||||||
r.m_ptr = nullptr;
|
ensure(is_same_ptr_test<T, U>(r.m_ptr));
|
||||||
|
|
||||||
|
single_ptr(std::move(r)).swap(*this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,9 +270,12 @@ namespace stx
|
||||||
}
|
}
|
||||||
|
|
||||||
// "Moving" "static cast"
|
// "Moving" "static cast"
|
||||||
template <typename U, typename = decltype(static_cast<U*>(std::declval<T*>())), typename = std::enable_if_t<is_same_ptr<U, T>()>>
|
template <typename U, typename = decltype(static_cast<U*>(std::declval<T*>())), typename = std::enable_if_t<is_same_ptr<U, T>() != same_ptr::no>>
|
||||||
explicit operator single_ptr<U>() && noexcept
|
explicit operator single_ptr<U>() && noexcept
|
||||||
{
|
{
|
||||||
|
if constexpr (is_same_ptr<U, T>() == same_ptr::maybe)
|
||||||
|
ensure(is_same_ptr_test<U, T>(m_ptr));
|
||||||
|
|
||||||
single_ptr<U> r;
|
single_ptr<U> r;
|
||||||
r.m_ptr = static_cast<decltype(r.m_ptr)>(std::exchange(m_ptr, nullptr));
|
r.m_ptr = static_cast<decltype(r.m_ptr)>(std::exchange(m_ptr, nullptr));
|
||||||
return r;
|
return r;
|
||||||
|
@ -424,10 +438,13 @@ namespace stx
|
||||||
d()->refs++;
|
d()->refs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
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> != same_ptr::no>>
|
||||||
shared_ptr(const shared_ptr<U>& r) noexcept
|
shared_ptr(const shared_ptr<U>& r) noexcept
|
||||||
: m_ptr(r.m_ptr)
|
|
||||||
{
|
{
|
||||||
|
if constexpr (is_same_ptr<T, U>() == same_ptr::maybe)
|
||||||
|
ensure(is_same_ptr_test<T, U>(r.m_ptr));
|
||||||
|
|
||||||
|
m_ptr = r.m_ptr;
|
||||||
if (m_ptr)
|
if (m_ptr)
|
||||||
d()->refs++;
|
d()->refs++;
|
||||||
}
|
}
|
||||||
|
@ -438,17 +455,23 @@ namespace stx
|
||||||
r.m_ptr = nullptr;
|
r.m_ptr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
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> != same_ptr::no>>
|
||||||
shared_ptr(shared_ptr<U>&& r) noexcept
|
shared_ptr(shared_ptr<U>&& r) noexcept
|
||||||
: m_ptr(r.m_ptr)
|
|
||||||
{
|
{
|
||||||
|
if constexpr (is_same_ptr<T, U>() == same_ptr::maybe)
|
||||||
|
ensure(is_same_ptr_test<T, U>(r.m_ptr));
|
||||||
|
|
||||||
|
m_ptr = r.m_ptr;
|
||||||
r.m_ptr = nullptr;
|
r.m_ptr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
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> != same_ptr::no>>
|
||||||
shared_ptr(single_ptr<U>&& r) noexcept
|
shared_ptr(single_ptr<U>&& r) noexcept
|
||||||
: m_ptr(r.m_ptr)
|
|
||||||
{
|
{
|
||||||
|
if constexpr (is_same_ptr<T, U>() == same_ptr::maybe)
|
||||||
|
ensure(is_same_ptr_test<T, U>(r.m_ptr));
|
||||||
|
|
||||||
|
m_ptr = r.m_ptr;
|
||||||
r.m_ptr = nullptr;
|
r.m_ptr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,9 +486,12 @@ namespace stx
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
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> != same_ptr::no>>
|
||||||
shared_ptr& operator=(const shared_ptr<U>& r) noexcept
|
shared_ptr& operator=(const shared_ptr<U>& r) noexcept
|
||||||
{
|
{
|
||||||
|
if constexpr (is_same_ptr<T, U>() == same_ptr::maybe)
|
||||||
|
ensure(is_same_ptr_test<T, U>(r.m_ptr));
|
||||||
|
|
||||||
shared_ptr(r).swap(*this);
|
shared_ptr(r).swap(*this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -476,16 +502,22 @@ namespace stx
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
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> != same_ptr::no>>
|
||||||
shared_ptr& operator=(shared_ptr<U>&& r) noexcept
|
shared_ptr& operator=(shared_ptr<U>&& r) noexcept
|
||||||
{
|
{
|
||||||
|
if constexpr (is_same_ptr<T, U>() == same_ptr::maybe)
|
||||||
|
ensure(is_same_ptr_test<T, U>(r.m_ptr));
|
||||||
|
|
||||||
shared_ptr(std::move(r)).swap(*this);
|
shared_ptr(std::move(r)).swap(*this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
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> != same_ptr::no>>
|
||||||
shared_ptr& operator=(single_ptr<U>&& r) noexcept
|
shared_ptr& operator=(single_ptr<U>&& r) noexcept
|
||||||
{
|
{
|
||||||
|
if constexpr (is_same_ptr<T, U>() == same_ptr::maybe)
|
||||||
|
ensure(is_same_ptr_test<T, U>(r.m_ptr));
|
||||||
|
|
||||||
shared_ptr(std::move(r)).swap(*this);
|
shared_ptr(std::move(r)).swap(*this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -503,9 +535,12 @@ namespace stx
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts to unique (single) ptr if reference is 1, otherwise returns null. Nullifies self.
|
// Converts to unique (single) ptr if reference is 1, otherwise returns null. Nullifies self.
|
||||||
template <typename U, typename = decltype(static_cast<U*>(std::declval<T*>())), typename = std::enable_if_t<is_same_ptr<U, T>()>>
|
template <typename U, typename = decltype(static_cast<U*>(std::declval<T*>())), typename = std::enable_if_t<is_same_ptr<U, T>() != same_ptr::no>>
|
||||||
explicit operator single_ptr<U>() && noexcept
|
explicit operator single_ptr<U>() && noexcept
|
||||||
{
|
{
|
||||||
|
if constexpr (is_same_ptr<U, T>() == same_ptr::maybe)
|
||||||
|
ensure(is_same_ptr_test<U, T>(m_ptr));
|
||||||
|
|
||||||
const auto o = d();
|
const auto o = d();
|
||||||
|
|
||||||
if (m_ptr && !--o->refs)
|
if (m_ptr && !--o->refs)
|
||||||
|
@ -588,9 +623,12 @@ namespace stx
|
||||||
}
|
}
|
||||||
|
|
||||||
// Basic "static cast" support
|
// Basic "static cast" support
|
||||||
template <typename U, typename = decltype(static_cast<U*>(std::declval<T*>())), typename = std::enable_if_t<is_same_ptr<U, T>()>>
|
template <typename U, typename = decltype(static_cast<U*>(std::declval<T*>())), typename = std::enable_if_t<is_same_ptr<U, T>() != same_ptr::no>>
|
||||||
explicit operator shared_ptr<U>() const& noexcept
|
explicit operator shared_ptr<U>() const& noexcept
|
||||||
{
|
{
|
||||||
|
if constexpr (is_same_ptr<U, T>() == same_ptr::maybe)
|
||||||
|
ensure(is_same_ptr_test<U, T>(m_ptr));
|
||||||
|
|
||||||
if (m_ptr)
|
if (m_ptr)
|
||||||
{
|
{
|
||||||
d()->refs++;
|
d()->refs++;
|
||||||
|
@ -602,9 +640,12 @@ namespace stx
|
||||||
}
|
}
|
||||||
|
|
||||||
// "Moving" "static cast"
|
// "Moving" "static cast"
|
||||||
template <typename U, typename = decltype(static_cast<U*>(std::declval<T*>())), typename = std::enable_if_t<is_same_ptr<U, T>()>>
|
template <typename U, typename = decltype(static_cast<U*>(std::declval<T*>())), typename = std::enable_if_t<is_same_ptr<U, T>() != same_ptr::no>>
|
||||||
explicit operator shared_ptr<U>() && noexcept
|
explicit operator shared_ptr<U>() && noexcept
|
||||||
{
|
{
|
||||||
|
if constexpr (is_same_ptr<U, T>() == same_ptr::maybe)
|
||||||
|
ensure(is_same_ptr_test<U, T>(m_ptr));
|
||||||
|
|
||||||
shared_ptr<U> r;
|
shared_ptr<U> r;
|
||||||
r.m_ptr = static_cast<decltype(r.m_ptr)>(std::exchange(m_ptr, nullptr));
|
r.m_ptr = static_cast<decltype(r.m_ptr)>(std::exchange(m_ptr, nullptr));
|
||||||
return r;
|
return r;
|
||||||
|
@ -660,29 +701,38 @@ namespace stx
|
||||||
d()->refs.raw() += 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> != same_ptr::no>>
|
||||||
atomic_ptr(const shared_ptr<U>& r) noexcept
|
atomic_ptr(const shared_ptr<U>& r) noexcept
|
||||||
: m_val(reinterpret_cast<uptr>(r.m_ptr) << c_ref_size)
|
|
||||||
{
|
{
|
||||||
|
if constexpr (is_same_ptr<T, U>() == same_ptr::maybe)
|
||||||
|
ensure(is_same_ptr_test<T, U>(r.m_ptr));
|
||||||
|
|
||||||
// Obtain a ref + as many refs as an atomic_ptr can additionally reference
|
// Obtain a ref + as many refs as an atomic_ptr can additionally reference
|
||||||
|
m_val = reinterpret_cast<uptr>(r.m_ptr) << c_ref_size;
|
||||||
if (m_val)
|
if (m_val)
|
||||||
d()->refs += c_ref_mask + 1;
|
d()->refs += c_ref_mask + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
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> != same_ptr::no>>
|
||||||
atomic_ptr(shared_ptr<U>&& r) noexcept
|
atomic_ptr(shared_ptr<U>&& r) noexcept
|
||||||
: m_val(reinterpret_cast<uptr>(r.m_ptr) << c_ref_size)
|
|
||||||
{
|
{
|
||||||
|
if constexpr (is_same_ptr<T, U>() == same_ptr::maybe)
|
||||||
|
ensure(is_same_ptr_test<T, U>(r.m_ptr));
|
||||||
|
|
||||||
|
m_val = reinterpret_cast<uptr>(r.m_ptr) << c_ref_size;
|
||||||
r.m_ptr = nullptr;
|
r.m_ptr = nullptr;
|
||||||
|
|
||||||
if (m_val)
|
if (m_val)
|
||||||
d()->refs += c_ref_mask;
|
d()->refs += 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> != same_ptr::no>>
|
||||||
atomic_ptr(single_ptr<U>&& r) noexcept
|
atomic_ptr(single_ptr<U>&& r) noexcept
|
||||||
: m_val(reinterpret_cast<uptr>(r.m_ptr) << c_ref_size)
|
|
||||||
{
|
{
|
||||||
|
if constexpr (is_same_ptr<T, U>() == same_ptr::maybe)
|
||||||
|
ensure(is_same_ptr_test<T, U>(r.m_ptr));
|
||||||
|
|
||||||
|
m_val = reinterpret_cast<uptr>(r.m_ptr) << c_ref_size;
|
||||||
r.m_ptr = nullptr;
|
r.m_ptr = nullptr;
|
||||||
|
|
||||||
if (m_val)
|
if (m_val)
|
||||||
|
@ -711,23 +761,32 @@ namespace stx
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
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> != same_ptr::no>>
|
||||||
atomic_ptr& operator=(const shared_ptr<U>& r) noexcept
|
atomic_ptr& operator=(const shared_ptr<U>& r) noexcept
|
||||||
{
|
{
|
||||||
|
if constexpr (is_same_ptr<T, U>() == same_ptr::maybe)
|
||||||
|
ensure(is_same_ptr_test<T, U>(r.m_ptr));
|
||||||
|
|
||||||
store(r);
|
store(r);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
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> != same_ptr::no>>
|
||||||
atomic_ptr& operator=(shared_ptr<U>&& r) noexcept
|
atomic_ptr& operator=(shared_ptr<U>&& r) noexcept
|
||||||
{
|
{
|
||||||
|
if constexpr (is_same_ptr<T, U>() == same_ptr::maybe)
|
||||||
|
ensure(is_same_ptr_test<T, U>(r.m_ptr));
|
||||||
|
|
||||||
store(std::move(r));
|
store(std::move(r));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
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> != same_ptr::no>>
|
||||||
atomic_ptr& operator=(single_ptr<U>&& r) noexcept
|
atomic_ptr& operator=(single_ptr<U>&& r) noexcept
|
||||||
{
|
{
|
||||||
|
if constexpr (is_same_ptr<T, U>() == same_ptr::maybe)
|
||||||
|
ensure(is_same_ptr_test<T, U>(r.m_ptr));
|
||||||
|
|
||||||
store(std::move(r));
|
store(std::move(r));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -988,9 +1047,12 @@ namespace stx
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unoptimized
|
// Unoptimized
|
||||||
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> != same_ptr::no>>
|
||||||
shared_type compare_and_swap(const shared_ptr<U>& cmp, shared_type exch)
|
shared_type compare_and_swap(const shared_ptr<U>& cmp, shared_type exch)
|
||||||
{
|
{
|
||||||
|
if constexpr (is_same_ptr<T, U>() == same_ptr::maybe)
|
||||||
|
ensure(is_same_ptr_test<T, U>(cmp.m_ptr));
|
||||||
|
|
||||||
shared_type old = cmp;
|
shared_type old = cmp;
|
||||||
|
|
||||||
if (compare_exchange(old, std::move(exch)))
|
if (compare_exchange(old, std::move(exch)))
|
||||||
|
@ -1004,9 +1066,12 @@ namespace stx
|
||||||
}
|
}
|
||||||
|
|
||||||
// More lightweight than compare_exchange
|
// More lightweight than compare_exchange
|
||||||
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> != same_ptr::no>>
|
||||||
bool compare_and_swap_test(const shared_ptr<U>& cmp, shared_type exch)
|
bool compare_and_swap_test(const shared_ptr<U>& cmp, shared_type exch)
|
||||||
{
|
{
|
||||||
|
if constexpr (is_same_ptr<T, U>() == same_ptr::maybe)
|
||||||
|
ensure(is_same_ptr_test<T, U>(cmp.m_ptr));
|
||||||
|
|
||||||
const uptr _old = reinterpret_cast<uptr>(cmp.m_ptr);
|
const uptr _old = reinterpret_cast<uptr>(cmp.m_ptr);
|
||||||
const uptr _new = reinterpret_cast<uptr>(exch.m_ptr);
|
const uptr _new = reinterpret_cast<uptr>(exch.m_ptr);
|
||||||
|
|
||||||
|
@ -1043,9 +1108,12 @@ namespace stx
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unoptimized
|
// Unoptimized
|
||||||
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> != same_ptr::no>>
|
||||||
shared_type compare_and_swap(const single_ptr<U>& cmp, shared_type exch)
|
shared_type compare_and_swap(const single_ptr<U>& cmp, shared_type exch)
|
||||||
{
|
{
|
||||||
|
if constexpr (is_same_ptr<T, U>() == same_ptr::maybe)
|
||||||
|
ensure(is_same_ptr_test<T, U>(cmp.m_ptr));
|
||||||
|
|
||||||
shared_type old = cmp;
|
shared_type old = cmp;
|
||||||
|
|
||||||
if (compare_exchange(old, std::move(exch)))
|
if (compare_exchange(old, std::move(exch)))
|
||||||
|
@ -1059,9 +1127,12 @@ namespace stx
|
||||||
}
|
}
|
||||||
|
|
||||||
// Supplementary
|
// Supplementary
|
||||||
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> != same_ptr::no>>
|
||||||
bool compare_and_swap_test(const single_ptr<U>& cmp, shared_type exch)
|
bool compare_and_swap_test(const single_ptr<U>& cmp, shared_type exch)
|
||||||
{
|
{
|
||||||
|
if constexpr (is_same_ptr<T, U>() == same_ptr::maybe)
|
||||||
|
ensure(is_same_ptr_test<T, U>(cmp.m_ptr));
|
||||||
|
|
||||||
return compare_and_swap_test(reinterpret_cast<const shared_ptr<U>&>(cmp), std::move(exch));
|
return compare_and_swap_test(reinterpret_cast<const shared_ptr<U>&>(cmp), std::move(exch));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1111,13 +1182,13 @@ namespace stx
|
||||||
return m_val != 0;
|
return m_val != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
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> != same_ptr::no>>
|
||||||
bool is_equal(const shared_ptr<U>& r) const noexcept
|
bool is_equal(const shared_ptr<U>& r) const noexcept
|
||||||
{
|
{
|
||||||
return observe() == r.get();
|
return observe() == r.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
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> != same_ptr::no>>
|
||||||
bool is_equal(const single_ptr<U>& r) const noexcept
|
bool is_equal(const single_ptr<U>& r) const noexcept
|
||||||
{
|
{
|
||||||
return observe() == r.get();
|
return observe() == r.get();
|
||||||
|
|
|
@ -255,7 +255,7 @@ namespace stx
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
static_assert(sizeof(As) > 0);
|
static_assert(sizeof(As) > 0);
|
||||||
static_assert(is_same_ptr<T, As>());
|
static_assert(is_same_ptr<T, As>() == same_ptr::yes); // TODO
|
||||||
return type_counter<Info>::template dyn_type<T, As>.index();
|
return type_counter<Info>::template dyn_type<T, As>.index();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -274,7 +274,7 @@ namespace stx
|
||||||
ATTR_PURE inline const Info& typedata() noexcept
|
ATTR_PURE inline const Info& typedata() noexcept
|
||||||
{
|
{
|
||||||
static_assert(sizeof(T) > 0 && sizeof(As) > 0);
|
static_assert(sizeof(T) > 0 && sizeof(As) > 0);
|
||||||
static_assert(is_same_ptr<T, As>());
|
static_assert(is_same_ptr<T, As>() == same_ptr::yes); // TODO
|
||||||
|
|
||||||
return type_counter<Info>::template dyn_type<T, As>;
|
return type_counter<Info>::template dyn_type<T, As>;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue