[libcxx-commits] [libcxx] [libc++] cv-qualified types in atomic and atomic_ref (P3323R1) (PR #121414)
via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Dec 31 13:10:33 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Damien L-G (dalg24)
<details>
<summary>Changes</summary>
Implement P3323R1 as a DR against C++11(?), respectively C++20, for `std::atomic` and `std::atomic_ref`.
The `std::atomic` changes are straightforward, adding a couple static assertions checking that the class template is only instantiated for cv-unqualified types, along with a test adapted from `libcxx/test/std/atomics/atomics.types.generic/trivially_copyable.verify.cpp`.
The `std::atomic_ref` changes are more involved. I started converting a subset of the tests to add coverage for volatile- and const-qualified types but I would like feedback before I process the rest.
---
Patch is 38.03 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/121414.diff
11 Files Affected:
- (modified) libcxx/docs/Status/Cxx2cPapers.csv (+1-1)
- (modified) libcxx/include/__atomic/atomic_ref.h (+212-64)
- (modified) libcxx/include/__atomic/support.h (+4)
- (modified) libcxx/include/__cxx03/__atomic/cxx_atomic_impl.h (+4)
- (modified) libcxx/test/std/atomics/atomics.ref/assign.pass.cpp (+29-13)
- (modified) libcxx/test/std/atomics/atomics.ref/convert.pass.cpp (+27-7)
- (modified) libcxx/test/std/atomics/atomics.ref/deduction.pass.cpp (+11-2)
- (modified) libcxx/test/std/atomics/atomics.ref/load.pass.cpp (+27-8)
- (modified) libcxx/test/std/atomics/atomics.ref/store.pass.cpp (+32-8)
- (modified) libcxx/test/std/atomics/atomics.ref/test_helper.h (+20-19)
- (added) libcxx/test/std/atomics/atomics.types.generic/cv_unqualified.verify.cpp (+25)
``````````diff
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index 3a8a794ca4ea1e..990c65a4993a3a 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -87,7 +87,7 @@
"`P3050R2 <https://wg21.link/P3050R2>`__","Fix C++26 by optimizing ``linalg::conjugated`` for noncomplex value types","2024-11 (Wrocław)","","",""
"`P3396R1 <https://wg21.link/P3396R1>`__","``std::execution`` wording fixes","2024-11 (Wrocław)","","",""
"`P2835R7 <https://wg21.link/P2835R7>`__","Expose ``std::atomic_ref``'s object address","2024-11 (Wrocław)","","",""
-"`P3323R1 <https://wg21.link/P3323R1>`__","cv-qualified types in ``atomic`` and ``atomic_ref``","2024-11 (Wrocław)","","",""
+"`P3323R1 <https://wg21.link/P3323R1>`__","cv-qualified types in ``atomic`` and ``atomic_ref``","2024-11 (Wrocław)","|Complete|","20","Implemented as DR against C++20."
"`P3508R0 <https://wg21.link/P3508R0>`__","Wording for ""constexpr for specialized memory algorithms""","2024-11 (Wrocław)","","",""
"`P3369R0 <https://wg21.link/P3369R0>`__","constexpr for ``uninitialized_default_construct``","2024-11 (Wrocław)","","",""
"`P3370R1 <https://wg21.link/P3370R1>`__","Add new library headers from C23","2024-11 (Wrocław)","","",""
diff --git a/libcxx/include/__atomic/atomic_ref.h b/libcxx/include/__atomic/atomic_ref.h
index eef15983b98331..f7ed626fed75da 100644
--- a/libcxx/include/__atomic/atomic_ref.h
+++ b/libcxx/include/__atomic/atomic_ref.h
@@ -29,7 +29,12 @@
#include <__cstddef/ptrdiff_t.h>
#include <__memory/addressof.h>
#include <__type_traits/has_unique_object_representation.h>
+#include <__type_traits/is_const.h>
+#include <__type_traits/is_pointer.h>
#include <__type_traits/is_trivially_copyable.h>
+#include <__type_traits/is_volatile.h>
+#include <__type_traits/remove_cv.h>
+#include <__type_traits/remove_pointer.h>
#include <cstdint>
#include <cstring>
@@ -110,7 +115,7 @@ struct __atomic_ref_base {
static constexpr size_t __min_alignment = (sizeof(_Tp) & (sizeof(_Tp) - 1)) || (sizeof(_Tp) > 16) ? 0 : sizeof(_Tp);
public:
- using value_type = _Tp;
+ using value_type = __remove_cv_t<_Tp>;
static constexpr size_t required_alignment = alignof(_Tp) > __min_alignment ? alignof(_Tp) : __min_alignment;
@@ -123,43 +128,50 @@ struct __atomic_ref_base {
_LIBCPP_HIDE_FROM_ABI bool is_lock_free() const noexcept { return __atomic_is_lock_free(sizeof(_Tp), __ptr_); }
- _LIBCPP_HIDE_FROM_ABI void store(_Tp __desired, memory_order __order = memory_order::seq_cst) const noexcept
- _LIBCPP_CHECK_STORE_MEMORY_ORDER(__order) {
+ _LIBCPP_HIDE_FROM_ABI void store(value_type __desired, memory_order __order = memory_order::seq_cst) const noexcept
+ requires(!is_const_v<_Tp>)
+ _LIBCPP_CHECK_STORE_MEMORY_ORDER(__order) {
_LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
__order == memory_order::relaxed || __order == memory_order::release || __order == memory_order::seq_cst,
"atomic_ref: memory order argument to atomic store operation is invalid");
__atomic_store(__ptr_, __clear_padding(__desired), std::__to_gcc_order(__order));
}
- _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __desired) const noexcept {
+ _LIBCPP_HIDE_FROM_ABI value_type operator=(value_type __desired) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
store(__desired);
return __desired;
}
- _LIBCPP_HIDE_FROM_ABI _Tp load(memory_order __order = memory_order::seq_cst) const noexcept
+ _LIBCPP_HIDE_FROM_ABI value_type load(memory_order __order = memory_order::seq_cst) const noexcept
_LIBCPP_CHECK_LOAD_MEMORY_ORDER(__order) {
_LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
__order == memory_order::relaxed || __order == memory_order::consume || __order == memory_order::acquire ||
__order == memory_order::seq_cst,
"atomic_ref: memory order argument to atomic load operation is invalid");
- alignas(_Tp) byte __mem[sizeof(_Tp)];
- auto* __ret = reinterpret_cast<_Tp*>(__mem);
+ alignas(value_type) byte __mem[sizeof(value_type)];
+ auto* __ret = reinterpret_cast<value_type*>(__mem);
__atomic_load(__ptr_, __ret, std::__to_gcc_order(__order));
return *__ret;
}
- _LIBCPP_HIDE_FROM_ABI operator _Tp() const noexcept { return load(); }
+ _LIBCPP_HIDE_FROM_ABI operator value_type() const noexcept { return load(); }
- _LIBCPP_HIDE_FROM_ABI _Tp exchange(_Tp __desired, memory_order __order = memory_order::seq_cst) const noexcept {
- alignas(_Tp) byte __mem[sizeof(_Tp)];
- auto* __ret = reinterpret_cast<_Tp*>(__mem);
+ _LIBCPP_HIDE_FROM_ABI value_type
+ exchange(value_type __desired, memory_order __order = memory_order::seq_cst) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ alignas(value_type) byte __mem[sizeof(value_type)];
+ auto* __ret = reinterpret_cast<value_type*>(__mem);
__atomic_exchange(__ptr_, __clear_padding(__desired), __ret, std::__to_gcc_order(__order));
return *__ret;
}
- _LIBCPP_HIDE_FROM_ABI bool
- compare_exchange_weak(_Tp& __expected, _Tp __desired, memory_order __success, memory_order __failure) const noexcept
- _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__success, __failure) {
+ _LIBCPP_HIDE_FROM_ABI bool compare_exchange_weak(
+ value_type& __expected, value_type __desired, memory_order __success, memory_order __failure) const noexcept
+ requires(!is_const_v<_Tp>)
+ _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__success, __failure) {
_LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
__failure == memory_order::relaxed || __failure == memory_order::consume ||
__failure == memory_order::acquire || __failure == memory_order::seq_cst,
@@ -172,9 +184,10 @@ struct __atomic_ref_base {
std::__to_gcc_order(__success),
std::__to_gcc_order(__failure));
}
- _LIBCPP_HIDE_FROM_ABI bool
- compare_exchange_strong(_Tp& __expected, _Tp __desired, memory_order __success, memory_order __failure) const noexcept
- _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__success, __failure) {
+ _LIBCPP_HIDE_FROM_ABI bool compare_exchange_strong(
+ value_type& __expected, value_type __desired, memory_order __success, memory_order __failure) const noexcept
+ requires(!is_const_v<_Tp>)
+ _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__success, __failure) {
_LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
__failure == memory_order::relaxed || __failure == memory_order::consume ||
__failure == memory_order::acquire || __failure == memory_order::seq_cst,
@@ -188,8 +201,10 @@ struct __atomic_ref_base {
std::__to_gcc_order(__failure));
}
- _LIBCPP_HIDE_FROM_ABI bool
- compare_exchange_weak(_Tp& __expected, _Tp __desired, memory_order __order = memory_order::seq_cst) const noexcept {
+ _LIBCPP_HIDE_FROM_ABI bool compare_exchange_weak(
+ value_type& __expected, value_type __desired, memory_order __order = memory_order::seq_cst) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
return __compare_exchange(
__ptr_,
std::addressof(__expected),
@@ -198,8 +213,10 @@ struct __atomic_ref_base {
std::__to_gcc_order(__order),
std::__to_gcc_failure_order(__order));
}
- _LIBCPP_HIDE_FROM_ABI bool
- compare_exchange_strong(_Tp& __expected, _Tp __desired, memory_order __order = memory_order::seq_cst) const noexcept {
+ _LIBCPP_HIDE_FROM_ABI bool compare_exchange_strong(
+ value_type& __expected, value_type __desired, memory_order __order = memory_order::seq_cst) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
return __compare_exchange(
__ptr_,
std::addressof(__expected),
@@ -209,7 +226,7 @@ struct __atomic_ref_base {
std::__to_gcc_failure_order(__order));
}
- _LIBCPP_HIDE_FROM_ABI void wait(_Tp __old, memory_order __order = memory_order::seq_cst) const noexcept
+ _LIBCPP_HIDE_FROM_ABI void wait(value_type __old, memory_order __order = memory_order::seq_cst) const noexcept
_LIBCPP_CHECK_WAIT_MEMORY_ORDER(__order) {
_LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
__order == memory_order::relaxed || __order == memory_order::consume || __order == memory_order::acquire ||
@@ -217,8 +234,16 @@ struct __atomic_ref_base {
"atomic_ref: memory order argument to atomic wait operation is invalid");
std::__atomic_wait(*this, __old, __order);
}
- _LIBCPP_HIDE_FROM_ABI void notify_one() const noexcept { std::__atomic_notify_one(*this); }
- _LIBCPP_HIDE_FROM_ABI void notify_all() const noexcept { std::__atomic_notify_all(*this); }
+ _LIBCPP_HIDE_FROM_ABI void notify_one() const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ std::__atomic_notify_one(*this);
+ }
+ _LIBCPP_HIDE_FROM_ABI void notify_all() const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ std::__atomic_notify_all(*this);
+ }
protected:
using _Aligned_Tp [[__gnu__::__aligned__(required_alignment)]] = _Tp;
@@ -243,6 +268,8 @@ struct atomic_ref : public __atomic_ref_base<_Tp> {
using __base = __atomic_ref_base<_Tp>;
+ static_assert(__base::is_always_lock_free || !is_volatile_v<_Tp>);
+
_LIBCPP_HIDE_FROM_ABI explicit atomic_ref(_Tp& __obj) : __base(__obj) {
_LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
reinterpret_cast<uintptr_t>(std::addressof(__obj)) % __base::required_alignment == 0,
@@ -251,17 +278,24 @@ struct atomic_ref : public __atomic_ref_base<_Tp> {
_LIBCPP_HIDE_FROM_ABI atomic_ref(const atomic_ref&) noexcept = default;
- _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __desired) const noexcept { return __base::operator=(__desired); }
+ _LIBCPP_HIDE_FROM_ABI __base::value_type operator=(__base::value_type __desired) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ return __base::operator=(__desired);
+ }
atomic_ref& operator=(const atomic_ref&) = delete;
};
template <class _Tp>
- requires(std::integral<_Tp> && !std::same_as<bool, _Tp>)
+ requires(std::integral<_Tp> && !std::same_as<bool, __remove_cv_t<_Tp>>)
struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> {
using __base = __atomic_ref_base<_Tp>;
+ static_assert(__base::is_always_lock_free || !is_volatile_v<_Tp>);
+
using difference_type = __base::value_type;
+ using value_type = __base::value_type;
_LIBCPP_HIDE_FROM_ABI explicit atomic_ref(_Tp& __obj) : __base(__obj) {
_LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
@@ -271,35 +305,90 @@ struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> {
_LIBCPP_HIDE_FROM_ABI atomic_ref(const atomic_ref&) noexcept = default;
- _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __desired) const noexcept { return __base::operator=(__desired); }
+ _LIBCPP_HIDE_FROM_ABI value_type operator=(value_type __desired) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ return __base::operator=(__desired);
+ }
atomic_ref& operator=(const atomic_ref&) = delete;
- _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept {
+ _LIBCPP_HIDE_FROM_ABI value_type
+ fetch_add(value_type __arg, memory_order __order = memory_order_seq_cst) const noexcept
+ requires(!is_const_v<value_type>)
+ {
return __atomic_fetch_add(this->__ptr_, __arg, std::__to_gcc_order(__order));
}
- _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept {
+ _LIBCPP_HIDE_FROM_ABI value_type
+ fetch_sub(value_type __arg, memory_order __order = memory_order_seq_cst) const noexcept
+ requires(!is_const_v<value_type>)
+ {
return __atomic_fetch_sub(this->__ptr_, __arg, std::__to_gcc_order(__order));
}
- _LIBCPP_HIDE_FROM_ABI _Tp fetch_and(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept {
+ _LIBCPP_HIDE_FROM_ABI value_type
+ fetch_and(value_type __arg, memory_order __order = memory_order_seq_cst) const noexcept
+ requires(!is_const_v<value_type>)
+ {
return __atomic_fetch_and(this->__ptr_, __arg, std::__to_gcc_order(__order));
}
- _LIBCPP_HIDE_FROM_ABI _Tp fetch_or(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept {
+ _LIBCPP_HIDE_FROM_ABI value_type
+ fetch_or(value_type __arg, memory_order __order = memory_order_seq_cst) const noexcept
+ requires(!is_const_v<value_type>)
+ {
return __atomic_fetch_or(this->__ptr_, __arg, std::__to_gcc_order(__order));
}
- _LIBCPP_HIDE_FROM_ABI _Tp fetch_xor(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept {
+ _LIBCPP_HIDE_FROM_ABI value_type
+ fetch_xor(value_type __arg, memory_order __order = memory_order_seq_cst) const noexcept
+ requires(!is_const_v<value_type>)
+ {
return __atomic_fetch_xor(this->__ptr_, __arg, std::__to_gcc_order(__order));
}
- _LIBCPP_HIDE_FROM_ABI _Tp operator++(int) const noexcept { return fetch_add(_Tp(1)); }
- _LIBCPP_HIDE_FROM_ABI _Tp operator--(int) const noexcept { return fetch_sub(_Tp(1)); }
- _LIBCPP_HIDE_FROM_ABI _Tp operator++() const noexcept { return fetch_add(_Tp(1)) + _Tp(1); }
- _LIBCPP_HIDE_FROM_ABI _Tp operator--() const noexcept { return fetch_sub(_Tp(1)) - _Tp(1); }
- _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __arg) const noexcept { return fetch_add(__arg) + __arg; }
- _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __arg) const noexcept { return fetch_sub(__arg) - __arg; }
- _LIBCPP_HIDE_FROM_ABI _Tp operator&=(_Tp __arg) const noexcept { return fetch_and(__arg) & __arg; }
- _LIBCPP_HIDE_FROM_ABI _Tp operator|=(_Tp __arg) const noexcept { return fetch_or(__arg) | __arg; }
- _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __arg) const noexcept { return fetch_xor(__arg) ^ __arg; }
+ _LIBCPP_HIDE_FROM_ABI value_type operator++(int) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ return fetch_add(value_type(1));
+ }
+ _LIBCPP_HIDE_FROM_ABI value_type operator--(int) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ return fetch_sub(value_type(1));
+ }
+ _LIBCPP_HIDE_FROM_ABI value_type operator++() const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ return fetch_add(value_type(1)) + value_type(1);
+ }
+ _LIBCPP_HIDE_FROM_ABI value_type operator--() const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ return fetch_sub(value_type(1)) - value_type(1);
+ }
+ _LIBCPP_HIDE_FROM_ABI value_type operator+=(value_type __arg) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ return fetch_add(__arg) + __arg;
+ }
+ _LIBCPP_HIDE_FROM_ABI value_type operator-=(value_type __arg) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ return fetch_sub(__arg) - __arg;
+ }
+ _LIBCPP_HIDE_FROM_ABI value_type operator&=(value_type __arg) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ return fetch_and(__arg) & __arg;
+ }
+ _LIBCPP_HIDE_FROM_ABI value_type operator|=(value_type __arg) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ return fetch_or(__arg) | __arg;
+ }
+ _LIBCPP_HIDE_FROM_ABI value_type operator^=(value_type __arg) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ return fetch_xor(__arg) ^ __arg;
+ }
};
template <class _Tp>
@@ -307,7 +396,10 @@ template <class _Tp>
struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> {
using __base = __atomic_ref_base<_Tp>;
+ static_assert(__base::is_always_lock_free || !is_volatile_v<_Tp>);
+
using difference_type = __base::value_type;
+ using value_type = __base::value_type;
_LIBCPP_HIDE_FROM_ABI explicit atomic_ref(_Tp& __obj) : __base(__obj) {
_LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
@@ -317,56 +409,112 @@ struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> {
_LIBCPP_HIDE_FROM_ABI atomic_ref(const atomic_ref&) noexcept = default;
- _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __desired) const noexcept { return __base::operator=(__desired); }
+ _LIBCPP_HIDE_FROM_ABI value_type operator=(value_type __desired) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ return __base::operator=(__desired);
+ }
atomic_ref& operator=(const atomic_ref&) = delete;
- _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept {
- _Tp __old = this->load(memory_order_relaxed);
- _Tp __new = __old + __arg;
+ _LIBCPP_HIDE_FROM_ABI value_type
+ fetch_add(value_type __arg, memory_order __order = memory_order_seq_cst) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ value_type __old = this->load(memory_order_relaxed);
+ value_type __new = __old + __arg;
while (!this->compare_exchange_weak(__old, __new, __order, memory_order_relaxed)) {
__new = __old + __arg;
}
return __old;
}
- _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __arg, memory_order __order = memory_order_seq_cst) const noexcept {
- _Tp __old = this->load(memory_order_relaxed);
- _Tp __new = __old - __arg;
+ _LIBCPP_HIDE_FROM_ABI value_type
+ fetch_sub(value_type __arg, memory_order __order = memory_order_seq_cst) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ value_type __old = this->load(memory_order_relaxed);
+ value_type __new = __old - __arg;
while (!this->compare_exchange_weak(__old, __new, __order, memory_order_relaxed)) {
__new = __old - __arg;
}
return __old;
}
- _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __arg) const noexcept { return fetch_add(__arg) + __arg; }
- _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __arg) const noexcept { return fetch_sub(__arg) - __arg; }
+ _LIBCPP_HIDE_FROM_ABI value_type operator+=(value_type __arg) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ return fetch_add(__arg) + __arg;
+ }
+ _LIBCPP_HIDE_FROM_ABI value_type operator-=(value_type __arg) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ return fetch_sub(__arg) - __arg;
+ }
};
template <class _Tp>
-struct atomic_ref<_Tp*> : public __atomic_ref_base<_Tp*> {
- using __base = __atomic_ref_base<_Tp*>;
+ requires(std::is_pointer_v<_Tp>)
+struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> {
+ using __base = __atomic_ref_base<_Tp>;
using difference_type = ptrdiff_t;
+ using value_type = typename __base::value_type;
- _LIBCPP_HIDE_FROM_ABI explicit atomic_ref(_Tp*& __ptr) : __base(__ptr) {}
+ _LIBCPP_HIDE_FROM_ABI explicit atomic_ref(_Tp& __ptr) : __base(__ptr) {}
- _LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __desired) const noexcept { return __base::operator=(__desired); }
+ _LIBCPP_HIDE_FROM_ABI value_type operator=(value_type __desired) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ return __base::operator=(__desired);
+ }
atomic_ref& operator=(const atomic_ref&) = delete;
- _LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __arg, memory_order __order = memory_order_seq_cst) const noexcept {
- return __atomic_fetch_add(this->__ptr_, __arg * sizeof(_Tp), std::__to_gcc_order(__order));
+ _LIBCPP_HIDE_FROM_ABI value_type
+ fetch_add(ptrdiff_t __arg, memory_order __order = memory_order_seq_cst) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ return __atomic_fetch_add(
+ this->__ptr_, __arg * sizeof(__remove_pointer_t<value_type>), std::__to_gcc_order(__order));
}
- _LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __arg, memory_order __order = memory_order_seq_cst) const noexcept {
- return __atomic_fetch_sub(this->__ptr_, __arg * sizeof(_Tp), std::__to_gcc_order(__order));
+ _LIBCPP_HIDE_FROM_ABI value_type
+ fetch_sub(ptrdiff_t __arg, memory_order __order = memory_order_seq_cst) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ return __atomic_fetch_sub(
+ this->__ptr_, __arg * sizeof(__remove_pointer_t<value_type>), std::__to_gcc_order(__order));
}
- _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) const noexcept { return fetch_add(1); }
- _LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) const noexcept { return fetch_sub(1); }
- _LIBCPP_HIDE_FROM_ABI _Tp* operator++() const noexcept { return fetch_add(1) + 1; }
- _LIBCPP_HIDE_FROM_ABI _Tp* operator--() const noexcept { return fetch_sub(1) - 1; }
- _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __arg) const noexcept { return fetch_add(__arg) + __arg; }
- _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __arg) const noexcept { return fetch_sub(__arg) - __arg; }
+ _LIBCPP_HIDE_FROM_ABI value_type operator++(int) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ return fetch_add(1);
+ }
+ _LIBCPP_HIDE_FROM_ABI value_type operator--(int) const noexcept
+ requires(!is_const_v<_Tp>)
+ {
+ return fetch_sub(1);
+ }
+ _LIBCPP_HIDE_FROM_ABI ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/121414
More information about the libcxx-commits
mailing list