fetch_sub(ptrdiff_t __d,
memory_order __m = memory_order_seq_cst) volatile noexcept
{ return __atomic_fetch_sub(&_M_p, _S_type_size(__d), int(__m)); }
+
+#if __glibcxx_atomic_min_max
+ _GLIBCXX_ALWAYS_INLINE __pointer_type
+ fetch_min(__pointer_type __p,
+ memory_order __m = memory_order_seq_cst) noexcept
+ { return __atomic_impl::__fetch_min(&_M_p, __p, __m); }
+
+ _GLIBCXX_ALWAYS_INLINE __pointer_type
+ fetch_min(__pointer_type __p,
+ memory_order __m = memory_order_seq_cst) volatile noexcept
+ { return __atomic_impl::__fetch_min(&_M_p, __p, __m); }
+
+ _GLIBCXX_ALWAYS_INLINE __pointer_type
+ fetch_max(__pointer_type __p,
+ memory_order __m = memory_order_seq_cst) noexcept
+ { return __atomic_impl::__fetch_max(&_M_p, __p, __m); }
+
+ _GLIBCXX_ALWAYS_INLINE __pointer_type
+ fetch_max(__pointer_type __p,
+ memory_order __m = memory_order_seq_cst) volatile noexcept
+ { return __atomic_impl::__fetch_max(&_M_p, __p, __m); }
+#endif
};
namespace __atomic_impl
memory_order __m = memory_order_seq_cst) const noexcept
{ return __atomic_impl::fetch_sub(this->_M_ptr, _S_type_size(__d), __m); }
+#if __glibcxx_atomic_min_max
+ _GLIBCXX_ALWAYS_INLINE value_type
+ fetch_min(value_type __i,
+ memory_order __m = memory_order_seq_cst) const noexcept
+ { return __atomic_impl::__fetch_min(this->_M_ptr, __i, __m); }
+
+ _GLIBCXX_ALWAYS_INLINE value_type
+ fetch_max(value_type __i,
+ memory_order __m = memory_order_seq_cst) const noexcept
+ { return __atomic_impl::__fetch_max(this->_M_ptr, __i, __m); }
+#endif
+
value_type
operator++(int) const noexcept
{ return fetch_add(1); }
#endif
return _M_b.fetch_sub(__d, __m);
}
+
+#if __glibcxx_atomic_min_max
+ __pointer_type
+ fetch_min(__pointer_type __p,
+ memory_order __m = memory_order_seq_cst) noexcept
+ { return _M_b.fetch_min(__p, __m); }
+
+ __pointer_type
+ fetch_min(__pointer_type __p,
+ memory_order __m = memory_order_seq_cst) volatile noexcept
+ { return _M_b.fetch_min(__p, __m); }
+
+ __pointer_type
+ fetch_max(__pointer_type __p,
+ memory_order __m = memory_order_seq_cst) noexcept
+ { return _M_b.fetch_max(__p, __m); }
+
+ __pointer_type
+ fetch_max(__pointer_type __p,
+ memory_order __m = memory_order_seq_cst) volatile noexcept
+ { return _M_b.fetch_max(__p, __m); }
+#endif
};
{ return __a->fetch_xor(__i, __m); }
#ifdef __cpp_lib_atomic_min_max
- template<typename _ITp>
- inline _ITp
- atomic_fetch_min_explicit(__atomic_base<_ITp>* __a,
- __atomic_val_t<_ITp> __i,
+ template<typename _Tp>
+ inline _Tp
+ atomic_fetch_min_explicit(atomic<_Tp>* __a,
+ __atomic_val_t<_Tp> __i,
memory_order __m) noexcept
{ return __a->fetch_min(__i, __m); }
- template<typename _ITp>
- inline _ITp
- atomic_fetch_min_explicit(volatile __atomic_base<_ITp>* __a,
- __atomic_val_t<_ITp> __i,
+ template<typename _Tp>
+ inline _Tp
+ atomic_fetch_min_explicit(volatile atomic<_Tp>* __a,
+ __atomic_val_t<_Tp> __i,
memory_order __m) noexcept
{ return __a->fetch_min(__i, __m); }
- template<typename _ITp>
- inline _ITp
- atomic_fetch_max_explicit(__atomic_base<_ITp>* __a,
- __atomic_val_t<_ITp> __i,
+ template<typename _Tp>
+ inline _Tp
+ atomic_fetch_max_explicit(atomic<_Tp>* __a,
+ __atomic_val_t<_Tp> __i,
memory_order __m) noexcept
{ return __a->fetch_max(__i, __m); }
- template<typename _ITp>
- inline _ITp
- atomic_fetch_max_explicit(volatile __atomic_base<_ITp>* __a,
- __atomic_val_t<_ITp> __i,
+ template<typename _Tp>
+ inline _Tp
+ atomic_fetch_max_explicit(volatile atomic<_Tp>* __a,
+ __atomic_val_t<_Tp> __i,
memory_order __m) noexcept
{ return __a->fetch_max(__i, __m); }
#endif
{ return atomic_fetch_xor_explicit(__a, __i, memory_order_seq_cst); }
#ifdef __cpp_lib_atomic_min_max
- template<typename _ITp>
- inline _ITp
- atomic_fetch_min(__atomic_base<_ITp>* __a,
- __atomic_val_t<_ITp> __i) noexcept
+ template<typename _Tp>
+ inline _Tp
+ atomic_fetch_min(atomic<_Tp>* __a,
+ __atomic_val_t<_Tp> __i) noexcept
{ return atomic_fetch_min_explicit(__a, __i, memory_order_seq_cst); }
- template<typename _ITp>
- inline _ITp
- atomic_fetch_min(volatile __atomic_base<_ITp>* __a,
- __atomic_val_t<_ITp> __i) noexcept
+ template<typename _Tp>
+ inline _Tp
+ atomic_fetch_min(volatile atomic<_Tp>* __a,
+ __atomic_val_t<_Tp> __i) noexcept
{ return atomic_fetch_min_explicit(__a, __i, memory_order_seq_cst); }
- template<typename _ITp>
- inline _ITp
- atomic_fetch_max(__atomic_base<_ITp>* __a,
- __atomic_val_t<_ITp> __i) noexcept
+ template<typename _Tp>
+ inline _Tp
+ atomic_fetch_max(atomic<_Tp>* __a,
+ __atomic_val_t<_Tp> __i) noexcept
{ return atomic_fetch_max_explicit(__a, __i, memory_order_seq_cst); }
- template<typename _ITp>
- inline _ITp
- atomic_fetch_max(volatile __atomic_base<_ITp>* __a,
- __atomic_val_t<_ITp> __i) noexcept
+ template<typename _Tp>
+ inline _Tp
+ atomic_fetch_max(volatile atomic<_Tp>* __a,
+ __atomic_val_t<_Tp> __i) noexcept
{ return atomic_fetch_max_explicit(__a, __i, memory_order_seq_cst); }
#endif
--- /dev/null
+// { dg-do run { target c++26 } }
+// { dg-require-atomic-cmpxchg-word "" }
+// { dg-add-options libatomic }
+
+#include <atomic>
+#include <testsuite_hooks.h>
+
+void test01() {
+ long arr[10] = {};
+
+ const auto mo = std::memory_order_relaxed;
+ std::atomic<long *> a(arr);
+
+ auto v = atomic_fetch_max(&a, arr + 5);
+ VERIFY(v == arr);
+ VERIFY(a == arr + 5);
+ v = atomic_fetch_max_explicit(&a, arr + 2, mo);
+ VERIFY(v == arr + 5);
+ VERIFY(a == arr + 5);
+
+ v = atomic_fetch_min(&a, arr + 3);
+ VERIFY(v == arr + 5);
+ VERIFY(a == arr + 3);
+ v = atomic_fetch_min_explicit(&a, arr + 5, mo);
+ VERIFY(v == arr + 3);
+ VERIFY(a == arr + 3);
+}
+
+void test02() {
+ char arr[10] = {};
+
+ const auto mo = std::memory_order_relaxed;
+ std::atomic<char *> a(arr);
+
+ auto v = atomic_fetch_max(&a, arr + 5);
+ VERIFY(v == arr);
+ VERIFY(a == arr + 5);
+ v = atomic_fetch_max_explicit(&a, arr + 2, mo);
+ VERIFY(v == arr + 5);
+ VERIFY(a == arr + 5);
+
+ v = atomic_fetch_min(&a, arr + 3);
+ VERIFY(v == arr + 5);
+ VERIFY(a == arr + 3);
+ v = atomic_fetch_min_explicit(&a, arr + 5, mo);
+ VERIFY(v == arr + 3);
+ VERIFY(a == arr + 3);
+}
+
+int main() {
+ test01();
+ test02();
+}
--- /dev/null
+// { dg-do run { target c++26 } }
+// { dg-require-atomic-cmpxchg-word "" }
+// { dg-add-options libatomic }
+
+#include <atomic>
+#include <testsuite_hooks.h>
+
+void test01() {
+ long arr[10] = {};
+ long *value;
+
+ {
+ const auto mo = std::memory_order_relaxed;
+ std::atomic_ref<long *> a(value);
+ bool ok = a.is_lock_free();
+ if constexpr (std::atomic_ref<long *>::is_always_lock_free)
+ VERIFY(ok);
+ a = arr;
+
+ auto v = a.fetch_max(arr + 5);
+ VERIFY(v == arr);
+ VERIFY(a == arr + 5);
+ v = a.fetch_max(arr + 2, mo);
+ VERIFY(v == arr + 5);
+ VERIFY(a == arr + 5);
+
+ v = a.fetch_min(arr + 3);
+ VERIFY(v == arr + 5);
+ VERIFY(a == arr + 3);
+ v = a.fetch_min(arr + 5, mo);
+ VERIFY(v == arr + 3);
+ VERIFY(a == arr + 3);
+ }
+
+ VERIFY(value == arr + 3);
+}
+
+void test02() {
+ char arr[10] = {};
+ char *value;
+
+ {
+ const auto mo = std::memory_order_relaxed;
+ std::atomic_ref<char *> a(value);
+ bool ok = a.is_lock_free();
+ if constexpr (std::atomic_ref<char *>::is_always_lock_free)
+ VERIFY(ok);
+ a = arr;
+
+ auto v = a.fetch_max(arr + 5);
+ VERIFY(v == arr);
+ VERIFY(a == arr + 5);
+ v = a.fetch_max(arr + 2, mo);
+ VERIFY(v == arr + 5);
+ VERIFY(a == arr + 5);
+
+ v = a.fetch_min(arr + 3);
+ VERIFY(v == arr + 5);
+ VERIFY(a == arr + 3);
+ v = a.fetch_min(arr + 5, mo);
+ VERIFY(v == arr + 3);
+ VERIFY(a == arr + 3);
+ }
+
+ VERIFY(value == arr + 3);
+}
+
+int main() {
+ test01();
+ test02();
+}