зеркало из https://github.com/microsoft/STL.git
<memory>: Fix atomic smart pointers array type interaction (#1339)
Co-authored-by: Nicole Mazzuca <mazzucan@outlook.com>
This commit is contained in:
Родитель
d89a32b2a4
Коммит
24b899e4ad
|
@ -3850,9 +3850,10 @@ class alignas(2 * sizeof(void*)) _Atomic_ptr_base {
|
|||
protected:
|
||||
constexpr _Atomic_ptr_base() noexcept = default;
|
||||
|
||||
_Atomic_ptr_base(_Ty* const _Px, _Ref_count_base* const _Ref) noexcept : _Ptr(_Px), _Repptr(_Ref) {}
|
||||
_Atomic_ptr_base(remove_extent_t<_Ty>* const _Px, _Ref_count_base* const _Ref) noexcept
|
||||
: _Ptr(_Px), _Repptr(_Ref) {}
|
||||
|
||||
void _Wait(_Ty* _Old, memory_order) const noexcept {
|
||||
void _Wait(remove_extent_t<_Ty>* _Old, memory_order) const noexcept {
|
||||
for (;;) {
|
||||
auto _Rep = _Repptr._Lock_and_load();
|
||||
bool _Equal = _Ptr.load(memory_order_relaxed) == _Old;
|
||||
|
@ -3872,7 +3873,7 @@ protected:
|
|||
_Ptr.notify_all();
|
||||
}
|
||||
|
||||
atomic<_Ty*> _Ptr{nullptr};
|
||||
atomic<remove_extent_t<_Ty>*> _Ptr{nullptr};
|
||||
mutable _Locked_pointer<_Ref_count_base> _Repptr;
|
||||
};
|
||||
|
||||
|
@ -3892,9 +3893,9 @@ public:
|
|||
|
||||
void store(shared_ptr<_Ty> _Value, const memory_order _Order = memory_order_seq_cst) noexcept {
|
||||
_Check_store_memory_order(_Order);
|
||||
const auto _Rep = this->_Repptr._Lock_and_load();
|
||||
_Ty* const _Tmp = _Value._Ptr;
|
||||
_Value._Ptr = this->_Ptr.load(memory_order_relaxed);
|
||||
const auto _Rep = this->_Repptr._Lock_and_load();
|
||||
remove_extent_t<_Ty>* const _Tmp = _Value._Ptr;
|
||||
_Value._Ptr = this->_Ptr.load(memory_order_relaxed);
|
||||
this->_Ptr.store(_Tmp, memory_order_relaxed);
|
||||
this->_Repptr._Store_and_unlock(_Value._Rep);
|
||||
_Value._Rep = _Rep;
|
||||
|
@ -3947,8 +3948,8 @@ public:
|
|||
_Check_memory_order(_Order);
|
||||
auto _Rep = this->_Repptr._Lock_and_load();
|
||||
if (this->_Ptr.load(memory_order_relaxed) == _Expected._Ptr && _Rep == _Expected._Rep) {
|
||||
_Ty* const _Tmp = _Desired._Ptr;
|
||||
_Desired._Ptr = this->_Ptr.load(memory_order_relaxed);
|
||||
remove_extent_t<_Ty>* const _Tmp = _Desired._Ptr;
|
||||
_Desired._Ptr = this->_Ptr.load(memory_order_relaxed);
|
||||
this->_Ptr.store(_Tmp, memory_order_relaxed);
|
||||
_STD swap(_Rep, _Desired._Rep);
|
||||
this->_Repptr._Store_and_unlock(_Rep);
|
||||
|
@ -4011,9 +4012,9 @@ public:
|
|||
|
||||
void store(weak_ptr<_Ty> _Value, const memory_order _Order = memory_order_seq_cst) noexcept {
|
||||
_Check_store_memory_order(_Order);
|
||||
const auto _Rep = this->_Repptr._Lock_and_load();
|
||||
_Ty* const _Tmp = _Value._Ptr;
|
||||
_Value._Ptr = this->_Ptr.load(memory_order_relaxed);
|
||||
const auto _Rep = this->_Repptr._Lock_and_load();
|
||||
remove_extent_t<_Ty>* const _Tmp = _Value._Ptr;
|
||||
_Value._Ptr = this->_Ptr.load(memory_order_relaxed);
|
||||
this->_Ptr.store(_Tmp, memory_order_relaxed);
|
||||
this->_Repptr._Store_and_unlock(_Value._Rep);
|
||||
_Value._Rep = _Rep;
|
||||
|
@ -4066,8 +4067,8 @@ public:
|
|||
_Check_memory_order(_Order);
|
||||
auto _Rep = this->_Repptr._Lock_and_load();
|
||||
if (this->_Ptr.load(memory_order_relaxed) == _Expected._Ptr && _Rep == _Expected._Rep) {
|
||||
_Ty* const _Tmp = _Desired._Ptr;
|
||||
_Desired._Ptr = this->_Ptr.load(memory_order_relaxed);
|
||||
remove_extent_t<_Ty>* const _Tmp = _Desired._Ptr;
|
||||
_Desired._Ptr = this->_Ptr.load(memory_order_relaxed);
|
||||
this->_Ptr.store(_Tmp, memory_order_relaxed);
|
||||
_STD swap(_Rep, _Desired._Rep);
|
||||
this->_Repptr._Store_and_unlock(_Rep);
|
||||
|
|
|
@ -108,7 +108,8 @@ void test_notify_all_notifies_all(UnderlyingType old_value, const UnderlyingType
|
|||
template <class UnderlyingType>
|
||||
void test_notify_all_notifies_all_ptr(UnderlyingType old_value, const UnderlyingType new_value,
|
||||
const std::chrono::steady_clock::duration waiting_duration) {
|
||||
test_notify_all_notifies_all_impl<std::atomic, UnderlyingType>(old_value, new_value, waiting_duration);
|
||||
// increased waiting_duration because timing assumption might not hold for atomic smart pointers
|
||||
test_notify_all_notifies_all_impl<std::atomic, UnderlyingType>(old_value, new_value, 3 * waiting_duration);
|
||||
}
|
||||
|
||||
|
||||
|
@ -228,6 +229,21 @@ inline void test_atomic_wait() {
|
|||
test_atomic_wait_func_ptr(std::make_shared<int>('a'), std::make_shared<int>('a'), waiting_duration);
|
||||
test_atomic_wait_func_ptr(
|
||||
std::weak_ptr{std::make_shared<int>('a')}, std::weak_ptr{std::make_shared<int>('a')}, waiting_duration);
|
||||
test_atomic_wait_func_ptr(std::make_shared<int[]>(0), std::make_shared<int[]>(0), waiting_duration);
|
||||
test_atomic_wait_func_ptr(
|
||||
std::weak_ptr{std::make_shared<int[]>(0)}, std::weak_ptr{std::make_shared<int[]>(0)}, waiting_duration);
|
||||
test_atomic_wait_func_ptr(std::make_shared<int[]>(1), std::make_shared<int[]>(1), waiting_duration);
|
||||
test_atomic_wait_func_ptr(
|
||||
std::weak_ptr{std::make_shared<int[]>(1)}, std::weak_ptr{std::make_shared<int[]>(1)}, waiting_duration);
|
||||
test_atomic_wait_func_ptr(std::make_shared<int[2]>(), std::make_shared<int[2]>(), waiting_duration);
|
||||
test_atomic_wait_func_ptr(
|
||||
std::weak_ptr{std::make_shared<int[2]>()}, std::weak_ptr{std::make_shared<int[2]>()}, waiting_duration);
|
||||
test_atomic_wait_func_ptr(std::make_shared<int[][2]>(2), std::make_shared<int[][2]>(2), waiting_duration);
|
||||
test_atomic_wait_func_ptr(
|
||||
std::weak_ptr{std::make_shared<int[][2]>(2)}, std::weak_ptr{std::make_shared<int[][2]>(2)}, waiting_duration);
|
||||
test_atomic_wait_func_ptr(std::make_shared<int[2][2]>(), std::make_shared<int[2][2]>(), waiting_duration);
|
||||
test_atomic_wait_func_ptr(
|
||||
std::weak_ptr{std::make_shared<int[2][2]>()}, std::weak_ptr{std::make_shared<int[2][2]>()}, waiting_duration);
|
||||
|
||||
test_notify_all_notifies_all<char>(1, 2, waiting_duration);
|
||||
test_notify_all_notifies_all<signed char>(1, 2, waiting_duration);
|
||||
|
@ -248,6 +264,25 @@ inline void test_atomic_wait() {
|
|||
test_notify_all_notifies_all(three_chars{1, 1, 3}, three_chars{1, 2, 3}, waiting_duration);
|
||||
test_notify_all_notifies_all(big_char_like{'a'}, big_char_like{'b'}, waiting_duration);
|
||||
|
||||
test_notify_all_notifies_all_ptr(std::make_shared<int>('a'), std::make_shared<int>('a'), waiting_duration);
|
||||
test_notify_all_notifies_all_ptr(
|
||||
std::weak_ptr{std::make_shared<int>('a')}, std::weak_ptr{std::make_shared<int>('a')}, waiting_duration);
|
||||
test_notify_all_notifies_all_ptr(std::make_shared<int[]>(0), std::make_shared<int[]>(0), waiting_duration);
|
||||
test_notify_all_notifies_all_ptr(
|
||||
std::weak_ptr{std::make_shared<int[]>(0)}, std::weak_ptr{std::make_shared<int[]>(0)}, waiting_duration);
|
||||
test_notify_all_notifies_all_ptr(std::make_shared<int[]>(1), std::make_shared<int[]>(1), waiting_duration);
|
||||
test_notify_all_notifies_all_ptr(
|
||||
std::weak_ptr{std::make_shared<int[]>(1)}, std::weak_ptr{std::make_shared<int[]>(1)}, waiting_duration);
|
||||
test_notify_all_notifies_all_ptr(std::make_shared<int[2]>(), std::make_shared<int[2]>(), waiting_duration);
|
||||
test_notify_all_notifies_all_ptr(
|
||||
std::weak_ptr{std::make_shared<int[2]>()}, std::weak_ptr{std::make_shared<int[2]>()}, waiting_duration);
|
||||
test_notify_all_notifies_all_ptr(std::make_shared<int[][2]>(2), std::make_shared<int[][2]>(2), waiting_duration);
|
||||
test_notify_all_notifies_all_ptr(
|
||||
std::weak_ptr{std::make_shared<int[][2]>(2)}, std::weak_ptr{std::make_shared<int[][2]>(2)}, waiting_duration);
|
||||
test_notify_all_notifies_all_ptr(std::make_shared<int[2][2]>(), std::make_shared<int[2][2]>(), waiting_duration);
|
||||
test_notify_all_notifies_all_ptr(
|
||||
std::weak_ptr{std::make_shared<int[2][2]>()}, std::weak_ptr{std::make_shared<int[2][2]>()}, waiting_duration);
|
||||
|
||||
#ifndef __clang__ // TRANSITION, LLVM-46685
|
||||
test_pad_bits<with_padding_bits<2>>(waiting_duration);
|
||||
test_pad_bits<with_padding_bits<4>>(waiting_duration);
|
||||
|
|
|
@ -21,7 +21,24 @@ weak_ptr<int> wptr1 = sptr1;
|
|||
atomic<shared_ptr<int>> atomic_sptr;
|
||||
atomic<weak_ptr<int>> atomic_wptr;
|
||||
|
||||
[[nodiscard]] bool weak_ptr_equal(const weak_ptr<int>& left, const weak_ptr<int>& right) {
|
||||
shared_ptr<int[]> sarrptr0 = make_shared<int[]>(0);
|
||||
shared_ptr<int[]> sarrptr1 = make_shared<int[]>(1);
|
||||
weak_ptr<int[]> warrptr0 = sarrptr0;
|
||||
weak_ptr<int[]> warrptr1 = sarrptr1;
|
||||
|
||||
atomic<shared_ptr<int[]>> atomic_sarrptr;
|
||||
atomic<weak_ptr<int[]>> atomic_warrptr;
|
||||
|
||||
shared_ptr<int[2]> sarrnptr0 = make_shared<int[2]>();
|
||||
shared_ptr<int[2]> sarrnptr1 = make_shared<int[2]>();
|
||||
weak_ptr<int[2]> warrnptr0 = sarrnptr0;
|
||||
weak_ptr<int[2]> warrnptr1 = sarrnptr1;
|
||||
|
||||
atomic<shared_ptr<int[2]>> atomic_sarrnptr;
|
||||
atomic<weak_ptr<int[2]>> atomic_warrnptr;
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] bool weak_ptr_equal(const weak_ptr<T>& left, const weak_ptr<T>& right) {
|
||||
return !(left.owner_before(right) || right.owner_before(left));
|
||||
}
|
||||
|
||||
|
@ -183,6 +200,324 @@ void test_weak_ptr_compare_exchange_strong() {
|
|||
}
|
||||
}
|
||||
|
||||
// Repeat test for unbounded array type.
|
||||
void test_shared_ptr_arr_load_store() {
|
||||
shared_ptr<int[]> sp0 = sarrptr0;
|
||||
shared_ptr<int[]> sp1 = sarrptr1;
|
||||
for (uintmax_t i = 0; i < iterations; ++i) {
|
||||
atomic_sarrptr = sp0;
|
||||
shared_ptr<int[]> temp = atomic_sarrptr;
|
||||
assert(temp == sp0 || temp == sp1);
|
||||
this_thread::yield();
|
||||
|
||||
atomic_sarrptr.store(sp1);
|
||||
temp = atomic_sarrptr.load();
|
||||
assert(temp == sp0 || temp == sp1);
|
||||
this_thread::yield();
|
||||
|
||||
atomic_sarrptr.store(sp0, memory_order::seq_cst);
|
||||
temp = atomic_sarrptr.load(memory_order::seq_cst);
|
||||
assert(temp == sp0 || temp == sp1);
|
||||
this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
void test_shared_ptr_arr_exchange() {
|
||||
shared_ptr<int[]> sp0 = sarrptr0;
|
||||
shared_ptr<int[]> sp1 = sarrptr1;
|
||||
for (uintmax_t i = 0; i < iterations; ++i) {
|
||||
shared_ptr<int[]> temp = atomic_sarrptr.exchange(sp0);
|
||||
assert(temp == sp0 || temp == sp1);
|
||||
this_thread::yield();
|
||||
|
||||
temp = atomic_sarrptr.exchange(sp1, memory_order::seq_cst);
|
||||
assert(temp == sp0 || temp == sp1);
|
||||
this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
void test_shared_ptr_arr_compare_exchange_weak() {
|
||||
shared_ptr<int[]> sp0 = sarrptr0;
|
||||
shared_ptr<int[]> sp1 = sarrptr1;
|
||||
for (uintmax_t i = 0; i < iterations; ++i) {
|
||||
shared_ptr<int[]> local = sp0;
|
||||
if (atomic_sarrptr.compare_exchange_weak(local, sp1)) {
|
||||
assert(local == sp0);
|
||||
} else {
|
||||
assert(local == sp1);
|
||||
}
|
||||
this_thread::yield();
|
||||
|
||||
local = sp1;
|
||||
if (atomic_sarrptr.compare_exchange_weak(local, sp0, memory_order::seq_cst, memory_order::seq_cst)) {
|
||||
assert(local == sp1);
|
||||
} else {
|
||||
assert(local == sp0);
|
||||
}
|
||||
this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
void test_shared_ptr_arr_compare_exchange_strong() {
|
||||
shared_ptr<int[]> sp0 = sarrptr0;
|
||||
shared_ptr<int[]> sp1 = sarrptr1;
|
||||
for (uintmax_t i = 0; i < iterations; ++i) {
|
||||
shared_ptr<int[]> local = sp0;
|
||||
if (atomic_sarrptr.compare_exchange_strong(local, sp1)) {
|
||||
assert(local == sp0);
|
||||
} else {
|
||||
assert(local == sp1);
|
||||
}
|
||||
this_thread::yield();
|
||||
|
||||
local = sp1;
|
||||
if (atomic_sarrptr.compare_exchange_strong(local, sp0, memory_order::seq_cst, memory_order::seq_cst)) {
|
||||
assert(local == sp1);
|
||||
} else {
|
||||
assert(local == sp0);
|
||||
}
|
||||
this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
void test_weak_ptr_arr_load_store() {
|
||||
weak_ptr<int[]> wp0 = warrptr0;
|
||||
weak_ptr<int[]> wp1 = warrptr1;
|
||||
for (uintmax_t i = 0; i < iterations; ++i) {
|
||||
atomic_warrptr = wp0;
|
||||
weak_ptr<int[]> temp = atomic_warrptr;
|
||||
assert(weak_ptr_equal(temp, wp0) || weak_ptr_equal(temp, wp1));
|
||||
this_thread::yield();
|
||||
|
||||
atomic_warrptr.store(wp1);
|
||||
temp = atomic_warrptr.load();
|
||||
assert(weak_ptr_equal(temp, wp0) || weak_ptr_equal(temp, wp1));
|
||||
this_thread::yield();
|
||||
|
||||
atomic_warrptr.store(wp0, memory_order::seq_cst);
|
||||
temp = atomic_warrptr.load(memory_order::seq_cst);
|
||||
assert(weak_ptr_equal(temp, wp0) || weak_ptr_equal(temp, wp1));
|
||||
this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
void test_weak_ptr_arr_exchange() {
|
||||
weak_ptr<int[]> wp0 = warrptr0;
|
||||
weak_ptr<int[]> wp1 = warrptr1;
|
||||
for (uintmax_t i = 0; i < iterations; ++i) {
|
||||
weak_ptr<int[]> temp = atomic_warrptr.exchange(wp0);
|
||||
assert(weak_ptr_equal(temp, wp0) || weak_ptr_equal(temp, wp1));
|
||||
this_thread::yield();
|
||||
|
||||
temp = atomic_warrptr.exchange(wp1, memory_order::seq_cst);
|
||||
assert(weak_ptr_equal(temp, wp0) || weak_ptr_equal(temp, wp1));
|
||||
this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
void test_weak_ptr_arr_compare_exchange_weak() {
|
||||
weak_ptr<int[]> wp0 = warrptr0;
|
||||
weak_ptr<int[]> wp1 = warrptr1;
|
||||
for (uintmax_t i = 0; i < iterations; ++i) {
|
||||
weak_ptr<int[]> local = wp0;
|
||||
if (atomic_warrptr.compare_exchange_weak(local, wp1)) {
|
||||
assert(weak_ptr_equal(local, wp0));
|
||||
} else {
|
||||
assert(weak_ptr_equal(local, wp1));
|
||||
}
|
||||
this_thread::yield();
|
||||
|
||||
local = wp1;
|
||||
if (atomic_warrptr.compare_exchange_weak(local, wp0, memory_order::seq_cst, memory_order::seq_cst)) {
|
||||
assert(weak_ptr_equal(local, wp1));
|
||||
} else {
|
||||
assert(weak_ptr_equal(local, wp0));
|
||||
}
|
||||
this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
void test_weak_ptr_arr_compare_exchange_strong() {
|
||||
weak_ptr<int[]> wp0 = warrptr0;
|
||||
weak_ptr<int[]> wp1 = warrptr1;
|
||||
for (uintmax_t i = 0; i < iterations; ++i) {
|
||||
weak_ptr<int[]> local = wp0;
|
||||
if (atomic_warrptr.compare_exchange_strong(local, wp1)) {
|
||||
assert(weak_ptr_equal(local, wp0));
|
||||
} else {
|
||||
assert(weak_ptr_equal(local, wp1));
|
||||
}
|
||||
this_thread::yield();
|
||||
|
||||
local = wp1;
|
||||
if (atomic_warrptr.compare_exchange_strong(local, wp0, memory_order::seq_cst, memory_order::seq_cst)) {
|
||||
assert(weak_ptr_equal(local, wp1));
|
||||
} else {
|
||||
assert(weak_ptr_equal(local, wp0));
|
||||
}
|
||||
this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
// Repeat test for bounded array type.
|
||||
void test_shared_ptr_arrn_load_store() {
|
||||
shared_ptr<int[2]> sp0 = sarrnptr0;
|
||||
shared_ptr<int[2]> sp1 = sarrnptr1;
|
||||
for (uintmax_t i = 0; i < iterations; ++i) {
|
||||
atomic_sarrnptr = sp0;
|
||||
shared_ptr<int[2]> temp = atomic_sarrnptr;
|
||||
assert(temp == sp0 || temp == sp1);
|
||||
this_thread::yield();
|
||||
|
||||
atomic_sarrnptr.store(sp1);
|
||||
temp = atomic_sarrnptr.load();
|
||||
assert(temp == sp0 || temp == sp1);
|
||||
this_thread::yield();
|
||||
|
||||
atomic_sarrnptr.store(sp0, memory_order::seq_cst);
|
||||
temp = atomic_sarrnptr.load(memory_order::seq_cst);
|
||||
assert(temp == sp0 || temp == sp1);
|
||||
this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
void test_shared_ptr_arrn_exchange() {
|
||||
shared_ptr<int[2]> sp0 = sarrnptr0;
|
||||
shared_ptr<int[2]> sp1 = sarrnptr1;
|
||||
for (uintmax_t i = 0; i < iterations; ++i) {
|
||||
shared_ptr<int[2]> temp = atomic_sarrnptr.exchange(sp0);
|
||||
assert(temp == sp0 || temp == sp1);
|
||||
this_thread::yield();
|
||||
|
||||
temp = atomic_sarrnptr.exchange(sp1, memory_order::seq_cst);
|
||||
assert(temp == sp0 || temp == sp1);
|
||||
this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
void test_shared_ptr_arrn_compare_exchange_weak() {
|
||||
shared_ptr<int[2]> sp0 = sarrnptr0;
|
||||
shared_ptr<int[2]> sp1 = sarrnptr1;
|
||||
for (uintmax_t i = 0; i < iterations; ++i) {
|
||||
shared_ptr<int[2]> local = sp0;
|
||||
if (atomic_sarrnptr.compare_exchange_weak(local, sp1)) {
|
||||
assert(local == sp0);
|
||||
} else {
|
||||
assert(local == sp1);
|
||||
}
|
||||
this_thread::yield();
|
||||
|
||||
local = sp1;
|
||||
if (atomic_sarrnptr.compare_exchange_weak(local, sp0, memory_order::seq_cst, memory_order::seq_cst)) {
|
||||
assert(local == sp1);
|
||||
} else {
|
||||
assert(local == sp0);
|
||||
}
|
||||
this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
void test_shared_ptr_arrn_compare_exchange_strong() {
|
||||
shared_ptr<int[2]> sp0 = sarrnptr0;
|
||||
shared_ptr<int[2]> sp1 = sarrnptr1;
|
||||
for (uintmax_t i = 0; i < iterations; ++i) {
|
||||
shared_ptr<int[2]> local = sp0;
|
||||
if (atomic_sarrnptr.compare_exchange_strong(local, sp1)) {
|
||||
assert(local == sp0);
|
||||
} else {
|
||||
assert(local == sp1);
|
||||
}
|
||||
this_thread::yield();
|
||||
|
||||
local = sp1;
|
||||
if (atomic_sarrnptr.compare_exchange_strong(local, sp0, memory_order::seq_cst, memory_order::seq_cst)) {
|
||||
assert(local == sp1);
|
||||
} else {
|
||||
assert(local == sp0);
|
||||
}
|
||||
this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
void test_weak_ptr_arrn_load_store() {
|
||||
weak_ptr<int[2]> wp0 = warrnptr0;
|
||||
weak_ptr<int[2]> wp1 = warrnptr1;
|
||||
for (uintmax_t i = 0; i < iterations; ++i) {
|
||||
atomic_warrnptr = wp0;
|
||||
weak_ptr<int[2]> temp = atomic_warrnptr;
|
||||
assert(weak_ptr_equal(temp, wp0) || weak_ptr_equal(temp, wp1));
|
||||
this_thread::yield();
|
||||
|
||||
atomic_warrnptr.store(wp1);
|
||||
temp = atomic_warrnptr.load();
|
||||
assert(weak_ptr_equal(temp, wp0) || weak_ptr_equal(temp, wp1));
|
||||
this_thread::yield();
|
||||
|
||||
atomic_warrnptr.store(wp0, memory_order::seq_cst);
|
||||
temp = atomic_warrnptr.load(memory_order::seq_cst);
|
||||
assert(weak_ptr_equal(temp, wp0) || weak_ptr_equal(temp, wp1));
|
||||
this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
void test_weak_ptr_arrn_exchange() {
|
||||
weak_ptr<int[2]> wp0 = warrnptr0;
|
||||
weak_ptr<int[2]> wp1 = warrnptr1;
|
||||
for (uintmax_t i = 0; i < iterations; ++i) {
|
||||
weak_ptr<int[2]> temp = atomic_warrnptr.exchange(wp0);
|
||||
assert(weak_ptr_equal(temp, wp0) || weak_ptr_equal(temp, wp1));
|
||||
this_thread::yield();
|
||||
|
||||
temp = atomic_warrnptr.exchange(wp1, memory_order::seq_cst);
|
||||
assert(weak_ptr_equal(temp, wp0) || weak_ptr_equal(temp, wp1));
|
||||
this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
void test_weak_ptr_arrn_compare_exchange_weak() {
|
||||
weak_ptr<int[2]> wp0 = warrnptr0;
|
||||
weak_ptr<int[2]> wp1 = warrnptr1;
|
||||
for (uintmax_t i = 0; i < iterations; ++i) {
|
||||
weak_ptr<int[2]> local = wp0;
|
||||
if (atomic_warrnptr.compare_exchange_weak(local, wp1)) {
|
||||
assert(weak_ptr_equal(local, wp0));
|
||||
} else {
|
||||
assert(weak_ptr_equal(local, wp1));
|
||||
}
|
||||
this_thread::yield();
|
||||
|
||||
local = wp1;
|
||||
if (atomic_warrnptr.compare_exchange_weak(local, wp0, memory_order::seq_cst, memory_order::seq_cst)) {
|
||||
assert(weak_ptr_equal(local, wp1));
|
||||
} else {
|
||||
assert(weak_ptr_equal(local, wp0));
|
||||
}
|
||||
this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
void test_weak_ptr_arrn_compare_exchange_strong() {
|
||||
weak_ptr<int[2]> wp0 = warrnptr0;
|
||||
weak_ptr<int[2]> wp1 = warrnptr1;
|
||||
for (uintmax_t i = 0; i < iterations; ++i) {
|
||||
weak_ptr<int[2]> local = wp0;
|
||||
if (atomic_warrnptr.compare_exchange_strong(local, wp1)) {
|
||||
assert(weak_ptr_equal(local, wp0));
|
||||
} else {
|
||||
assert(weak_ptr_equal(local, wp1));
|
||||
}
|
||||
this_thread::yield();
|
||||
|
||||
local = wp1;
|
||||
if (atomic_warrnptr.compare_exchange_strong(local, wp0, memory_order::seq_cst, memory_order::seq_cst)) {
|
||||
assert(weak_ptr_equal(local, wp1));
|
||||
} else {
|
||||
assert(weak_ptr_equal(local, wp0));
|
||||
}
|
||||
this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
void run_test(void (*fp)()) {
|
||||
thread thr0(fp);
|
||||
thread thr1(fp);
|
||||
|
@ -222,6 +557,25 @@ void ensure_nonmember_calls_compile() {
|
|||
}
|
||||
}
|
||||
|
||||
template <class AtomicType>
|
||||
void ensure_member_calls_compile() {
|
||||
AtomicType instance;
|
||||
const AtomicType constInstance;
|
||||
auto loaded = instance.load();
|
||||
loaded = constInstance.load();
|
||||
loaded = instance;
|
||||
loaded = constInstance;
|
||||
instance.store(loaded);
|
||||
loaded = instance.exchange(instance);
|
||||
loaded = instance.exchange(constInstance);
|
||||
if (instance.compare_exchange_weak(loaded, constInstance)) {
|
||||
// intentionally empty
|
||||
}
|
||||
if (instance.compare_exchange_strong(loaded, constInstance)) {
|
||||
// intentionally empty
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef __EDG__ // TRANSITION, DevCom-1656924
|
||||
// LWG-3661: constinit atomic<shared_ptr<T>> a(nullptr); should work
|
||||
constinit atomic<shared_ptr<bool>> a{};
|
||||
|
@ -245,6 +599,34 @@ int main() {
|
|||
run_test(test_weak_ptr_compare_exchange_strong);
|
||||
ensure_nonmember_calls_compile<atomic<shared_ptr<int>>>();
|
||||
ensure_nonmember_calls_compile<atomic<weak_ptr<int>>>();
|
||||
run_test(test_shared_ptr_arr_load_store);
|
||||
run_test(test_shared_ptr_arr_exchange);
|
||||
run_test(test_shared_ptr_arr_compare_exchange_weak);
|
||||
run_test(test_shared_ptr_arr_compare_exchange_strong);
|
||||
run_test(test_weak_ptr_arr_load_store);
|
||||
run_test(test_weak_ptr_arr_exchange);
|
||||
run_test(test_weak_ptr_arr_compare_exchange_weak);
|
||||
run_test(test_weak_ptr_arr_compare_exchange_strong);
|
||||
ensure_nonmember_calls_compile<atomic<shared_ptr<int[]>>>();
|
||||
ensure_nonmember_calls_compile<atomic<weak_ptr<int[]>>>();
|
||||
run_test(test_shared_ptr_arrn_load_store);
|
||||
run_test(test_shared_ptr_arrn_exchange);
|
||||
run_test(test_shared_ptr_arrn_compare_exchange_weak);
|
||||
run_test(test_shared_ptr_arrn_compare_exchange_strong);
|
||||
run_test(test_weak_ptr_arrn_load_store);
|
||||
run_test(test_weak_ptr_arrn_exchange);
|
||||
run_test(test_weak_ptr_arrn_compare_exchange_weak);
|
||||
run_test(test_weak_ptr_arrn_compare_exchange_strong);
|
||||
ensure_nonmember_calls_compile<atomic<shared_ptr<int[2]>>>();
|
||||
ensure_nonmember_calls_compile<atomic<weak_ptr<int[2]>>>();
|
||||
ensure_nonmember_calls_compile<atomic<shared_ptr<int[][2]>>>();
|
||||
ensure_nonmember_calls_compile<atomic<weak_ptr<int[][2]>>>();
|
||||
ensure_nonmember_calls_compile<atomic<shared_ptr<int[2][2]>>>();
|
||||
ensure_nonmember_calls_compile<atomic<weak_ptr<int[2][2]>>>();
|
||||
ensure_member_calls_compile<atomic<shared_ptr<int[][2]>>>();
|
||||
ensure_member_calls_compile<atomic<weak_ptr<int[][2]>>>();
|
||||
ensure_member_calls_compile<atomic<shared_ptr<int[2][2]>>>();
|
||||
ensure_member_calls_compile<atomic<weak_ptr<int[2][2]>>>();
|
||||
|
||||
#ifdef _DEBUG
|
||||
sptr0 = {};
|
||||
|
@ -253,6 +635,20 @@ int main() {
|
|||
wptr1 = {};
|
||||
atomic_sptr.store({});
|
||||
atomic_wptr.store({});
|
||||
|
||||
sarrptr0 = {};
|
||||
sarrptr1 = {};
|
||||
warrptr0 = {};
|
||||
warrptr1 = {};
|
||||
atomic_sarrptr.store({});
|
||||
atomic_warrptr.store({});
|
||||
|
||||
sarrnptr0 = {};
|
||||
sarrnptr1 = {};
|
||||
warrnptr0 = {};
|
||||
warrnptr1 = {};
|
||||
atomic_sarrnptr.store({});
|
||||
atomic_warrnptr.store({});
|
||||
assert(!_CrtDumpMemoryLeaks());
|
||||
#endif // _DEBUG
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче