On Wed, 29 Sept 2021 at 13:13, Jonathan Wakely wrote:
> We repeat this *a lot*. When I started work on this I defined a
> non-member function in the __atomic_impl namespace:

I've attached my incomplete patch from when I was working on this.
diff --cc libstdc++-v3/include/bits/atomic_base.h
index 71e1de078b5,35023ad30a8..00000000000
--- a/libstdc++-v3/include/bits/atomic_base.h
+++ b/libstdc++-v3/include/bits/atomic_base.h
@@@ -944,6 -952,28 +944,27 @@@ _GLIBCXX_BEGIN_NAMESPACE_VERSIO
      template<typename _Tp>
        using _Val = remove_volatile_t<_Tp>;
  
+     template<typename _Tp>
+       constexpr bool
+       __maybe_has_padding()
+       {
 -#if _GLIBCXX_HAVE_BUILTIN_HAS_UNIQ_OBJ_REP
 -      return !__has_unique_object_representations(_Tp);
++#if __has_builtin(__has_unique_object_representations)
++      return !__has_unique_object_representations(_Tp)
++        && !is_floating_point<_Tp>::value;
+ #else
+       return true;
+ #endif
+       }
+ 
+     template<typename _Tp>
+       _GLIBCXX_ALWAYS_INLINE void
+       __clear_padding(_Tp& __val) noexcept
+       {
 -      auto* __ptr = std::__addressof(__val);
+ #if __has_builtin(__builtin_clear_padding)
 -      __builtin_clear_padding(__ptr);
++      __builtin_clear_padding(std::__addressof(__val));
+ #endif
 -      return __ptr;
+       }
+ 
      // As above, but for difference_type arguments.
      template<typename _Tp>
        using _Diff = conditional_t<is_pointer_v<_Tp>, ptrdiff_t, _Val<_Tp>>;
@@@ -984,13 -1015,26 +1006,26 @@@
      template<typename _Tp>
        _GLIBCXX_ALWAYS_INLINE bool
        compare_exchange_weak(_Tp* __ptr, _Val<_Tp>& __expected,
-                           _Val<_Tp> __desired, memory_order __success,
-                           memory_order __failure) noexcept
+                           _Val<_Tp> __desired,
+                           memory_order __success, memory_order __failure,
+                           bool __weak = true) noexcept
        {
 +      __glibcxx_assert(__is_valid_cmpexch_failure_order(__failure));
- 
+ #if __has_builtin(__builtin_clear_padding)
+       if _GLIBCXX_CONSTEXPR17 (__maybe_has_padding<_Tp>())
+         {
+           _Val<_Tp> __expected0 = __expected;
+           auto* __exp = __atomic_impl::__clear_padding(__expected0);
+           auto* __des = __atomic_impl::__clear_padding(__desired);
+           if (__atomic_compare_exchange(__ptr, __exp, __des, __weak,
+                                         int(__success), int(__failure)))
+             return true;
+           __builtin_memcpy(std::__addressof(__expected), __exp, sizeof(_Tp));
+           return false;
+         }
 -      else
+ #endif
        return __atomic_compare_exchange(__ptr, std::__addressof(__expected),
-                                        std::__addressof(__desired), true,
+                                        std::__addressof(__desired), __weak,
                                         int(__success), int(__failure));
        }
  
@@@ -1000,11 -1044,8 +1035,9 @@@
                              _Val<_Tp> __desired, memory_order __success,
                              memory_order __failure) noexcept
        {
 +      __glibcxx_assert(__is_valid_cmpexch_failure_order(__failure));
- 
-       return __atomic_compare_exchange(__ptr, std::__addressof(__expected),
-                                        std::__addressof(__desired), false,
-                                        int(__success), int(__failure));
+       return compare_exchange_weak(__ptr, __expected, __desired, __success,
+                                    __failure, false);
        }
  
  #if __cpp_lib_atomic_wait

Reply via email to