From 4a883ba6eab66c3e4a123f805a388506b463cd36 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 15 Dec 2020 11:19:41 +0300 Subject: [PATCH] atomic.hpp: use SFINAE for waitable atomic detection Add default_mask<> variable. Refactor get_value<>(). --- rpcs3/util/atomic.hpp | 109 ++++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 51 deletions(-) diff --git a/rpcs3/util/atomic.hpp b/rpcs3/util/atomic.hpp index 2c10195a92..00d0cccfcf 100644 --- a/rpcs3/util/atomic.hpp +++ b/rpcs3/util/atomic.hpp @@ -114,6 +114,36 @@ namespace atomic_wait constexpr op op_ne = op::eq | op_flag::inverse; + constexpr struct any_value_t + { + template + operator T() const noexcept + { + return T(); + } + } any_value; + + template ().observe())> + inline __m128i default_mask = sizeof(T) <= 8 + ? _mm_cvtsi64_si128(UINT64_MAX >> ((64 - sizeof(T) * 8) & 63)) + : _mm_set1_epi64x(-1); + + template ().observe())> + constexpr __m128i get_value(X&, T value = T{}, ...) + { + static_assert((sizeof(T) & (sizeof(T) - 1)) == 0); + static_assert(sizeof(T) <= 16); + + if constexpr (sizeof(T) <= 8) + { + return _mm_cvtsi64_si128(std::bit_cast, T>(value)); + } + else if constexpr (sizeof(T) == 16) + { + return std::bit_cast<__m128i>(value); + } + } + struct info { const void* data; @@ -121,29 +151,13 @@ namespace atomic_wait __m128i old; __m128i mask; - template - static constexpr __m128i get_value(T value = T{}) + template ().observe())> + constexpr void set_value(X& a, T value = T{}) { - static_assert((sizeof(T) & (sizeof(T) - 1)) == 0); - static_assert(sizeof(T) <= 16); - - if constexpr (sizeof(T) <= 8) - { - return _mm_cvtsi64_si128(std::bit_cast, T>(value)); - } - else if constexpr (sizeof(T) == 16) - { - return std::bit_cast<__m128i>(value); - } + old = get_value(a, value); } - template - constexpr void set_value(T value = T{}) - { - old = get_value(value); - } - - template + template ().observe())> constexpr void set_mask(T value) { static_assert((sizeof(T) & (sizeof(T) - 1)) == 0); @@ -159,23 +173,10 @@ namespace atomic_wait } } - template + template ().observe())> constexpr void set_mask() { - mask = get_mask(); - } - - template - static constexpr __m128i get_mask() - { - if constexpr (sizeof(T) <= 8) - { - return _mm_cvtsi64_si128(UINT64_MAX >> ((64 - sizeof(T) * 8) & 63)); - } - else - { - return _mm_set1_epi64x(-1); - } + mask = default_mask; } }; @@ -194,9 +195,9 @@ namespace atomic_wait constexpr list& operator=(const list&) noexcept = default; - template - constexpr list(atomic_t&... vars) - : m_info{{&vars.raw(), sizeof(U), info::get_value(), info::get_mask()}...} + template ().template wait(any_value))...>> + constexpr list(U&... vars) + : m_info{{&vars, sizeof(vars.observe()), get_value(vars), default_mask}...} { static_assert(sizeof...(U) == Max, "Inconsistent amount of atomics."); } @@ -207,7 +208,7 @@ namespace atomic_wait static_assert(sizeof...(U) == Max, "Inconsistent amount of values."); auto* ptr = m_info; - ((ptr++)->template set_value(values), ...); + ((ptr->template set_value(*static_cast(ptr->data), values), ptr++), ...); return *this; } @@ -221,25 +222,25 @@ namespace atomic_wait return *this; } - template - constexpr void set(atomic_t& var, U value) + template ().template wait(any_value))>> + constexpr void set(T2& var, U value) { static_assert(Index < Max); - m_info[Index].data = &var.raw(); - m_info[Index].size = sizeof(T2) | (static_cast(Flags) << 8); - m_info[Index].template set_value(value); + m_info[Index].data = &var; + m_info[Index].size = sizeof(var.observe()) | (static_cast(Flags) << 8); + m_info[Index].template set_value(var, value); m_info[Index].template set_mask(); } - template - constexpr void set(atomic_t& var, U value, V mask) + template ().template wait(any_value))>> + constexpr void set(T2& var, U value, V mask) { static_assert(Index < Max); - m_info[Index].data = &var.raw(); - m_info[Index].size = sizeof(T2) | (static_cast(Flags) << 8); - m_info[Index].template set_value(value); + m_info[Index].data = &var; + m_info[Index].size = sizeof(var.observe()) | (static_cast(Flags) << 8); + m_info[Index].template set_value(var, value); m_info[Index].template set_mask(mask); } @@ -253,8 +254,8 @@ namespace atomic_wait } }; - template - list(atomic_t&... vars) -> list; + template ().template wait(any_value))...>> + list(T&... vars) -> list; // RDTSC with adjustment for being unique u64 get_unique_tsc(); @@ -1719,3 +1720,9 @@ public: base::notify_all(1); } }; + +namespace atomic_wait +{ + template + inline __m128i default_mask> = _mm_cvtsi32_si128(1); +}