[libc++] Update atomic synopsis and tests.

While looking at LWG-2988 and P0558 it seems the issues were already
implemented, but the synopsis wasn't updated. Some of the tests didn't
validate the `noexcept` status. A few tests were missing completely:
- `atomic_wait_explicit`
- `atomic_notify_one`
- `atomic_notify_all`

Mark P0558 as complete, didn't investigate which version of libc++ first
includes this. It seems the paper has been retroactively applied. I
couldn't find whether this is correct, but looking at cppreference it
seems intended.

Completes
- LWG-2988 Clause 32 cleanup missed one typename
- P0558 Resolving atomic<T> named base class inconsistencies

Reviewed By: #libc, ldionne

Differential Revision: https://reviews.llvm.org/D103765
This commit is contained in:
Mark de Wever 2021-06-06 14:48:08 +02:00
parent 6cac17e365
commit a76e698787
29 changed files with 575 additions and 348 deletions

View File

@ -101,7 +101,7 @@
"`P0518R1 <https://wg21.link/P0518R1>`__","LWG","Allowing copies as arguments to function objects given to parallel algorithms in response to CH11","Kona","",""
"`P0523R1 <https://wg21.link/P0523R1>`__","LWG","Wording for CH 10: Complexity of parallel algorithms","Kona","",""
"`P0548R1 <https://wg21.link/P0548R1>`__","LWG","common_type and duration","Kona","|Complete|","5.0"
"`P0558R1 <https://wg21.link/P0558R1>`__","LWG","Resolving atomic<T> named base class inconsistencies","Kona","",""
"`P0558R1 <https://wg21.link/P0558R1>`__","LWG","Resolving atomic<T> named base class inconsistencies","Kona","|Complete|",""
"`P0574R1 <https://wg21.link/P0574R1>`__","LWG","Algorithm Complexity Constraints and Parallel Overloads","Kona","",""
"`P0599R1 <https://wg21.link/P0599R1>`__","LWG","noexcept for hash functions","Kona","|Complete|","5.0"
"`P0604R0 <https://wg21.link/P0604R0>`__","LWG","Resolving GB 55, US 84, US 85, US 86","Kona","|Complete|",""

1 Paper # Group Paper Name Meeting Status First released version
101 `P0518R1 <https://wg21.link/P0518R1>`__ LWG Allowing copies as arguments to function objects given to parallel algorithms in response to CH11 Kona
102 `P0523R1 <https://wg21.link/P0523R1>`__ LWG Wording for CH 10: Complexity of parallel algorithms Kona
103 `P0548R1 <https://wg21.link/P0548R1>`__ LWG common_type and duration Kona |Complete| 5.0
104 `P0558R1 <https://wg21.link/P0558R1>`__ LWG Resolving atomic<T> named base class inconsistencies Kona |Complete|
105 `P0574R1 <https://wg21.link/P0574R1>`__ LWG Algorithm Complexity Constraints and Parallel Overloads Kona
106 `P0599R1 <https://wg21.link/P0599R1>`__ LWG noexcept for hash functions Kona |Complete| 5.0
107 `P0604R0 <https://wg21.link/P0604R0>`__ LWG Resolving GB 55, US 84, US 85, US 86 Kona |Complete|

View File

@ -34,7 +34,7 @@
"`2980 <https://wg21.link/LWG2980>`__","Cannot compare_exchange empty pointers","Albuquerque","",""
"`2981 <https://wg21.link/LWG2981>`__","Remove redundant deduction guides from standard library","Albuquerque","",""
"`2982 <https://wg21.link/LWG2982>`__","Making size_type consistent in associative container deduction guides","Albuquerque","",""
"`2988 <https://wg21.link/LWG2988>`__","Clause 32 cleanup missed one typename","Albuquerque","",""
"`2988 <https://wg21.link/LWG2988>`__","Clause 32 cleanup missed one typename","Albuquerque","|Complete|","13.0"
"`2993 <https://wg21.link/LWG2993>`__","reference_wrapper<T> conversion from T&&","Albuquerque","|Complete|","13.0"
"`2998 <https://wg21.link/LWG2998>`__","Requirements on function objects passed to {``forward_``,}list-specific algorithms","Albuquerque","|Nothing To Do|",""
"`3001 <https://wg21.link/LWG3001>`__","weak_ptr::element_type needs remove_extent_t","Albuquerque","",""

1 Issue # Issue Name Meeting Status First released version
34 `2980 <https://wg21.link/LWG2980>`__ Cannot compare_exchange empty pointers Albuquerque
35 `2981 <https://wg21.link/LWG2981>`__ Remove redundant deduction guides from standard library Albuquerque
36 `2982 <https://wg21.link/LWG2982>`__ Making size_type consistent in associative container deduction guides Albuquerque
37 `2988 <https://wg21.link/LWG2988>`__ Clause 32 cleanup missed one typename Albuquerque |Complete| 13.0
38 `2993 <https://wg21.link/LWG2993>`__ reference_wrapper<T> conversion from T&& Albuquerque |Complete| 13.0
39 `2998 <https://wg21.link/LWG2998>`__ Requirements on function objects passed to {``forward_``,}list-specific algorithms Albuquerque |Nothing To Do|
40 `3001 <https://wg21.link/LWG3001>`__ weak_ptr::element_type needs remove_extent_t Albuquerque

View File

@ -263,196 +263,137 @@ struct atomic<T*>
};
template <class T>
bool atomic_is_lock_free(const volatile atomic<T>* obj) noexcept;
// [atomics.nonmembers], non-member functions
template<class T>
bool atomic_is_lock_free(const volatile atomic<T>*) noexcept;
template<class T>
bool atomic_is_lock_free(const atomic<T>*) noexcept;
template<class T>
void atomic_store(volatile atomic<T>*, atomic<T>::value_type) noexcept;
template<class T>
void atomic_store(atomic<T>*, atomic<T>::value_type) noexcept;
template<class T>
void atomic_store_explicit(volatile atomic<T>*, atomic<T>::value_type,
memory_order) noexcept;
template<class T>
void atomic_store_explicit(atomic<T>*, atomic<T>::value_type,
memory_order) noexcept;
template<class T>
T atomic_load(const volatile atomic<T>*) noexcept;
template<class T>
T atomic_load(const atomic<T>*) noexcept;
template<class T>
T atomic_load_explicit(const volatile atomic<T>*, memory_order) noexcept;
template<class T>
T atomic_load_explicit(const atomic<T>*, memory_order) noexcept;
template<class T>
T atomic_exchange(volatile atomic<T>*, atomic<T>::value_type) noexcept;
template<class T>
T atomic_exchange(atomic<T>*, atomic<T>::value_type) noexcept;
template<class T>
T atomic_exchange_explicit(volatile atomic<T>*, atomic<T>::value_type,
memory_order) noexcept;
template<class T>
T atomic_exchange_explicit(atomic<T>*, atomic<T>::value_type,
memory_order) noexcept;
template<class T>
bool atomic_compare_exchange_weak(volatile atomic<T>*, atomic<T>::value_type*,
atomic<T>::value_type) noexcept;
template<class T>
bool atomic_compare_exchange_weak(atomic<T>*, atomic<T>::value_type*,
atomic<T>::value_type) noexcept;
template<class T>
bool atomic_compare_exchange_strong(volatile atomic<T>*, atomic<T>::value_type*,
atomic<T>::value_type) noexcept;
template<class T>
bool atomic_compare_exchange_strong(atomic<T>*, atomic<T>::value_type*,
atomic<T>::value_type) noexcept;
template<class T>
bool atomic_compare_exchange_weak_explicit(volatile atomic<T>*, atomic<T>::value_type*,
atomic<T>::value_type,
memory_order, memory_order) noexcept;
template<class T>
bool atomic_compare_exchange_weak_explicit(atomic<T>*, atomic<T>::value_type*,
atomic<T>::value_type,
memory_order, memory_order) noexcept;
template<class T>
bool atomic_compare_exchange_strong_explicit(volatile atomic<T>*, atomic<T>::value_type*,
atomic<T>::value_type,
memory_order, memory_order) noexcept;
template<class T>
bool atomic_compare_exchange_strong_explicit(atomic<T>*, atomic<T>::value_type*,
atomic<T>::value_type,
memory_order, memory_order) noexcept;
template <class T>
bool atomic_is_lock_free(const atomic<T>* obj) noexcept;
template<class T>
T atomic_fetch_add(volatile atomic<T>*, atomic<T>::difference_type) noexcept;
template<class T>
T atomic_fetch_add(atomic<T>*, atomic<T>::difference_type) noexcept;
template<class T>
T atomic_fetch_add_explicit(volatile atomic<T>*, atomic<T>::difference_type,
memory_order) noexcept;
template<class T>
T atomic_fetch_add_explicit(atomic<T>*, atomic<T>::difference_type,
memory_order) noexcept;
template<class T>
T atomic_fetch_sub(volatile atomic<T>*, atomic<T>::difference_type) noexcept;
template<class T>
T atomic_fetch_sub(atomic<T>*, atomic<T>::difference_type) noexcept;
template<class T>
T atomic_fetch_sub_explicit(volatile atomic<T>*, atomic<T>::difference_type,
memory_order) noexcept;
template<class T>
T atomic_fetch_sub_explicit(atomic<T>*, atomic<T>::difference_type,
memory_order) noexcept;
template<class T>
T atomic_fetch_and(volatile atomic<T>*, atomic<T>::value_type) noexcept;
template<class T>
T atomic_fetch_and(atomic<T>*, atomic<T>::value_type) noexcept;
template<class T>
T atomic_fetch_and_explicit(volatile atomic<T>*, atomic<T>::value_type,
memory_order) noexcept;
template<class T>
T atomic_fetch_and_explicit(atomic<T>*, atomic<T>::value_type,
memory_order) noexcept;
template<class T>
T atomic_fetch_or(volatile atomic<T>*, atomic<T>::value_type) noexcept;
template<class T>
T atomic_fetch_or(atomic<T>*, atomic<T>::value_type) noexcept;
template<class T>
T atomic_fetch_or_explicit(volatile atomic<T>*, atomic<T>::value_type,
memory_order) noexcept;
template<class T>
T atomic_fetch_or_explicit(atomic<T>*, atomic<T>::value_type,
memory_order) noexcept;
template<class T>
T atomic_fetch_xor(volatile atomic<T>*, atomic<T>::value_type) noexcept;
template<class T>
T atomic_fetch_xor(atomic<T>*, atomic<T>::value_type) noexcept;
template<class T>
T atomic_fetch_xor_explicit(volatile atomic<T>*, atomic<T>::value_type,
memory_order) noexcept;
template<class T>
T atomic_fetch_xor_explicit(atomic<T>*, atomic<T>::value_type,
memory_order) noexcept;
template <class T>
void atomic_store(volatile atomic<T>* obj, T desr) noexcept;
template <class T>
void atomic_store(atomic<T>* obj, T desr) noexcept;
template <class T>
void atomic_store_explicit(volatile atomic<T>* obj, T desr, memory_order m) noexcept;
template <class T>
void atomic_store_explicit(atomic<T>* obj, T desr, memory_order m) noexcept;
template <class T>
T atomic_load(const volatile atomic<T>* obj) noexcept;
template <class T>
T atomic_load(const atomic<T>* obj) noexcept;
template <class T>
T atomic_load_explicit(const volatile atomic<T>* obj, memory_order m) noexcept;
template <class T>
T atomic_load_explicit(const atomic<T>* obj, memory_order m) noexcept;
template <class T>
T atomic_exchange(volatile atomic<T>* obj, T desr) noexcept;
template <class T>
T atomic_exchange(atomic<T>* obj, T desr) noexcept;
template <class T>
T atomic_exchange_explicit(volatile atomic<T>* obj, T desr, memory_order m) noexcept;
template <class T>
T atomic_exchange_explicit(atomic<T>* obj, T desr, memory_order m) noexcept;
template <class T>
bool atomic_compare_exchange_weak(volatile atomic<T>* obj, T* expc, T desr) noexcept;
template <class T>
bool atomic_compare_exchange_weak(atomic<T>* obj, T* expc, T desr) noexcept;
template <class T>
bool atomic_compare_exchange_strong(volatile atomic<T>* obj, T* expc, T desr) noexcept;
template <class T>
bool atomic_compare_exchange_strong(atomic<T>* obj, T* expc, T desr) noexcept;
template <class T>
bool atomic_compare_exchange_weak_explicit(volatile atomic<T>* obj, T* expc,
T desr,
memory_order s, memory_order f) noexcept;
template <class T>
bool atomic_compare_exchange_weak_explicit(atomic<T>* obj, T* expc, T desr,
memory_order s, memory_order f) noexcept;
template <class T>
bool atomic_compare_exchange_strong_explicit(volatile atomic<T>* obj,
T* expc, T desr,
memory_order s, memory_order f) noexcept;
template <class T>
bool atomic_compare_exchange_strong_explicit(atomic<T>* obj, T* expc,
T desr,
memory_order s, memory_order f) noexcept;
template <class T>
void atomic_wait(const volatile atomic<T>* obj, T old) noexcept;
template <class T>
void atomic_wait(const atomic<T>* obj, T old) noexcept;
template <class T>
void atomic_wait_explicit(const volatile atomic<T>* obj, T old, memory_order m) noexcept;
template <class T>
void atomic_wait_explicit(const atomic<T>* obj, T old, memory_order m) noexcept;
template <class T>
void atomic_one(volatile atomic<T>* obj) noexcept;
template <class T>
void atomic_one(atomic<T>* obj) noexcept;
template <class T>
void atomic_all(volatile atomic<T>* obj) noexcept;
template <class T>
void atomic_all(atomic<T>* obj) noexcept;
template <class Integral>
Integral atomic_fetch_add(volatile atomic<Integral>* obj, Integral op) noexcept;
template <class Integral>
Integral atomic_fetch_add(atomic<Integral>* obj, Integral op) noexcept;
template <class Integral>
Integral atomic_fetch_add_explicit(volatile atomic<Integral>* obj, Integral op,
memory_order m) noexcept;
template <class Integral>
Integral atomic_fetch_add_explicit(atomic<Integral>* obj, Integral op,
memory_order m) noexcept;
template <class Integral>
Integral atomic_fetch_sub(volatile atomic<Integral>* obj, Integral op) noexcept;
template <class Integral>
Integral atomic_fetch_sub(atomic<Integral>* obj, Integral op) noexcept;
template <class Integral>
Integral atomic_fetch_sub_explicit(volatile atomic<Integral>* obj, Integral op,
memory_order m) noexcept;
template <class Integral>
Integral atomic_fetch_sub_explicit(atomic<Integral>* obj, Integral op,
memory_order m) noexcept;
template <class Integral>
Integral atomic_fetch_and(volatile atomic<Integral>* obj, Integral op) noexcept;
template <class Integral>
Integral atomic_fetch_and(atomic<Integral>* obj, Integral op) noexcept;
template <class Integral>
Integral atomic_fetch_and_explicit(volatile atomic<Integral>* obj, Integral op,
memory_order m) noexcept;
template <class Integral>
Integral atomic_fetch_and_explicit(atomic<Integral>* obj, Integral op,
memory_order m) noexcept;
template <class Integral>
Integral atomic_fetch_or(volatile atomic<Integral>* obj, Integral op) noexcept;
template <class Integral>
Integral atomic_fetch_or(atomic<Integral>* obj, Integral op) noexcept;
template <class Integral>
Integral atomic_fetch_or_explicit(volatile atomic<Integral>* obj, Integral op,
memory_order m) noexcept;
template <class Integral>
Integral atomic_fetch_or_explicit(atomic<Integral>* obj, Integral op,
memory_order m) noexcept;
template <class Integral>
Integral atomic_fetch_xor(volatile atomic<Integral>* obj, Integral op) noexcept;
template <class Integral>
Integral atomic_fetch_xor(atomic<Integral>* obj, Integral op) noexcept;
template <class Integral>
Integral atomic_fetch_xor_explicit(volatile atomic<Integral>* obj, Integral op,
memory_order m) noexcept;
template <class Integral>
Integral atomic_fetch_xor_explicit(atomic<Integral>* obj, Integral op,
memory_order m) noexcept;
template <class T>
T* atomic_fetch_add(volatile atomic<T*>* obj, ptrdiff_t op) noexcept;
template <class T>
T* atomic_fetch_add(atomic<T*>* obj, ptrdiff_t op) noexcept;
template <class T>
T* atomic_fetch_add_explicit(volatile atomic<T*>* obj, ptrdiff_t op,
memory_order m) noexcept;
template <class T>
T* atomic_fetch_add_explicit(atomic<T*>* obj, ptrdiff_t op, memory_order m) noexcept;
template <class T>
T* atomic_fetch_sub(volatile atomic<T*>* obj, ptrdiff_t op) noexcept;
template <class T>
T* atomic_fetch_sub(atomic<T*>* obj, ptrdiff_t op) noexcept;
template <class T>
T* atomic_fetch_sub_explicit(volatile atomic<T*>* obj, ptrdiff_t op,
memory_order m) noexcept;
template <class T>
T* atomic_fetch_sub_explicit(atomic<T*>* obj, ptrdiff_t op, memory_order m) noexcept;
template<class T>
void atomic_wait(const volatile atomic<T>*, atomic<T>::value_type);
template<class T>
void atomic_wait(const atomic<T>*, atomic<T>::value_type);
template<class T>
void atomic_wait_explicit(const volatile atomic<T>*, atomic<T>::value_type,
memory_order);
template<class T>
void atomic_wait_explicit(const atomic<T>*, atomic<T>::value_type,
memory_order);
template<class T>
void atomic_notify_one(volatile atomic<T>*);
template<class T>
void atomic_notify_one(atomic<T>*);
template<class T>
void atomic_notify_all(volatile atomic<T>*);
template<class T>
void atomic_notify_all(atomic<T>*);
// Atomics for standard typedef types
@ -564,10 +505,10 @@ void atomic_signal_fence(memory_order m) noexcept;
// deprecated
template <class T>
void atomic_init(volatile atomic<T>* obj, typename atomic<T>::value_type desr) noexcept;
void atomic_init(volatile atomic<T>* obj, atomic<T>::value_type desr) noexcept;
template <class T>
void atomic_init(atomic<T>* obj, typename atomic<T>::value_type desr) noexcept;
void atomic_init(atomic<T>* obj, atomic<T>::value_type desr) noexcept;
#define ATOMIC_VAR_INIT(value) see below

View File

@ -8,17 +8,20 @@
//
// UNSUPPORTED: libcpp-has-no-threads
// XFAIL: !non-lockfree-atomics
// ... assertion fails line 34
// <atomic>
// template <class T>
// bool
// atomic_compare_exchange_strong(volatile atomic<T>* obj, T* expc, T desr);
// atomic_compare_exchange_strong(volatile atomic<T>*,
// atomic<T>::value_type*,
// atomic<T>::value_type) noexcept;
//
// template <class T>
// bool
// atomic_compare_exchange_strong(atomic<T>* obj, T* expc, T desr);
// atomic_compare_exchange_strong(atomic<T>*,
// atomic<T>::value_type*,
// atomic<T>::value_type) noexcept;
#include <atomic>
#include <type_traits>
@ -40,6 +43,8 @@ struct TestFn {
assert(std::atomic_compare_exchange_strong(&a, &t, T(3)) == false);
assert(a == T(2));
assert(t == T(2));
ASSERT_NOEXCEPT(std::atomic_compare_exchange_strong(&a, &t, T(3)));
}
{
typedef std::atomic<T> A;
@ -51,6 +56,8 @@ struct TestFn {
assert(std::atomic_compare_exchange_strong(&a, &t, T(3)) == false);
assert(a == T(2));
assert(t == T(2));
ASSERT_NOEXCEPT(std::atomic_compare_exchange_strong(&a, &t, T(3)));
}
}
};

View File

@ -8,20 +8,22 @@
//
// UNSUPPORTED: libcpp-has-no-threads
// XFAIL: !non-lockfree-atomics
// ... assertion fails line 38
// <atomic>
// template <class T>
// bool
// atomic_compare_exchange_strong_explicit(volatile atomic<T>* obj, T* expc,
// T desr,
// memory_order s, memory_order f);
// atomic_compare_exchange_strong_explicit(volatile atomic<T>*,
// atomic<T>::value_type*,
// atomic<T>::value_type,
// memory_order, memory_order) noexcept;
//
// template <class T>
// bool
// atomic_compare_exchange_strong_explicit(atomic<T>* obj, T* expc, T desr,
// memory_order s, memory_order f);
// atomic_compare_exchange_strong_explicit(atomic<T>*,
// atomic<T>::value_type*,
// atomic<T>::value_type,
// memory_order, memory_order) noexcept;
#include <atomic>
#include <type_traits>
@ -45,6 +47,9 @@ struct TestFn {
std::memory_order_seq_cst, std::memory_order_seq_cst) == false);
assert(a == T(2));
assert(t == T(2));
ASSERT_NOEXCEPT(std::atomic_compare_exchange_strong_explicit(&a, &t, T(3), std::memory_order_seq_cst,
std::memory_order_seq_cst));
}
{
typedef std::atomic<T> A;
@ -58,6 +63,9 @@ struct TestFn {
std::memory_order_seq_cst, std::memory_order_seq_cst) == false);
assert(a == T(2));
assert(t == T(2));
ASSERT_NOEXCEPT(std::atomic_compare_exchange_strong_explicit(&a, &t, T(3), std::memory_order_seq_cst,
std::memory_order_seq_cst));
}
}
};

View File

@ -8,17 +8,20 @@
//
// UNSUPPORTED: libcpp-has-no-threads
// XFAIL: !non-lockfree-atomics
// ... assertion fails line 34
// <atomic>
// template <class T>
// bool
// atomic_compare_exchange_weak(volatile atomic<T>* obj, T* expc, T desr);
// atomic_compare_exchange_weak(volatile atomic<T>*,
// atomic<T>::value_type*,
// atomic<T>::value_type) noexcept;
//
// template <class T>
// bool
// atomic_compare_exchange_weak(atomic<T>* obj, T* expc, T desr);
// atomic_compare_exchange_weak(atomic<T>*,
// atomic<T>::value_type*,
// atomic<T>::value_type) noexcept;
#include <atomic>
#include <type_traits>
@ -41,6 +44,8 @@ struct TestFn {
assert(std::atomic_compare_exchange_weak(&a, &t, T(3)) == false);
assert(a == T(2));
assert(t == T(2));
ASSERT_NOEXCEPT(std::atomic_compare_exchange_weak(&a, &t, T(3)));
}
{
typedef std::atomic<T> A;
@ -52,6 +57,8 @@ struct TestFn {
assert(std::atomic_compare_exchange_weak(&a, &t, T(3)) == false);
assert(a == T(2));
assert(t == T(2));
ASSERT_NOEXCEPT(std::atomic_compare_exchange_weak(&a, &t, T(3)));
}
}
};

View File

@ -8,20 +8,22 @@
//
// UNSUPPORTED: libcpp-has-no-threads
// XFAIL: !non-lockfree-atomics
// ... assertion fails line 38
// <atomic>
// template <class T>
// bool
// atomic_compare_exchange_weak_explicit(volatile atomic<T>* obj, T* expc,
// T desr,
// memory_order s, memory_order f);
// atomic_compare_exchange_weak_explicit(volatile atomic<T>*,
// atomic<T>::value_type*,
// atomic<T>::value_type,
// memory_order, memory_order) noexcept;
//
// template <class T>
// bool
// atomic_compare_exchange_weak_explicit(atomic<T>* obj, T* expc, T desr,
// memory_order s, memory_order f);
// atomic_compare_exchange_weak_explicit(atomic<T>*,
// atomic<T>::value_type*,
// atomic<T>::value_type,
// memory_order, memory_order) noexcept;
#include <atomic>
#include <type_traits>
@ -47,6 +49,9 @@ struct TestFn {
std::memory_order_seq_cst, std::memory_order_seq_cst) == false);
assert(a == T(2));
assert(t == T(2));
ASSERT_NOEXCEPT(std::atomic_compare_exchange_weak_explicit(&a, &t, T(3), std::memory_order_seq_cst,
std::memory_order_seq_cst));
}
{
typedef std::atomic<T> A;
@ -60,6 +65,9 @@ struct TestFn {
std::memory_order_seq_cst, std::memory_order_seq_cst) == false);
assert(a == T(2));
assert(t == T(2));
ASSERT_NOEXCEPT(std::atomic_compare_exchange_weak_explicit(&a, &t, T(3), std::memory_order_seq_cst,
std::memory_order_seq_cst));
}
}
};

View File

@ -8,17 +8,16 @@
//
// UNSUPPORTED: libcpp-has-no-threads
// XFAIL: !non-lockfree-atomics
// ... fails assertion line 31
// <atomic>
// template <class T>
// T
// atomic_exchange(volatile atomic<T>* obj, T desr);
// atomic_exchange(volatile atomic<T>*, atomic<T>::value_type) noexcept;
//
// template <class T>
// T
// atomic_exchange(atomic<T>* obj, T desr);
// atomic_exchange(atomic<T>*, atomic<T>::value_type) noexcept;
#include <atomic>
#include <type_traits>
@ -37,6 +36,9 @@ struct TestFn {
volatile A vt(T(3));
assert(std::atomic_exchange(&vt, T(4)) == T(3));
assert(vt == T(4));
ASSERT_NOEXCEPT(std::atomic_exchange(&t, T(2)));
ASSERT_NOEXCEPT(std::atomic_exchange(&vt, T(4)));
}
};

View File

@ -8,17 +8,18 @@
//
// UNSUPPORTED: libcpp-has-no-threads
// XFAIL: !non-lockfree-atomics
// ... assertion fails line 32
// <atomic>
// template <class T>
// T
// atomic_exchange_explicit(volatile atomic<T>* obj, T desr, memory_order m);
// atomic_exchange_explicit(volatile atomic<T>*, atomic<T>::value_type,
// memory_order) noexcept;
//
// template <class T>
// T
// atomic_exchange_explicit(atomic<T>* obj, T desr, memory_order m);
// atomic_exchange_explicit(atomic<T>*, atomic<T>::value_type,
// memory_order) noexcept;
#include <atomic>
#include <type_traits>
@ -39,6 +40,9 @@ struct TestFn {
assert(std::atomic_exchange_explicit(&vt, T(4), std::memory_order_seq_cst)
== T(3));
assert(vt == T(4));
ASSERT_NOEXCEPT(std::atomic_exchange_explicit(&t, T(2), std::memory_order_seq_cst));
ASSERT_NOEXCEPT(std::atomic_exchange_explicit(&vt, T(4), std::memory_order_seq_cst));
}
};

View File

@ -10,21 +10,13 @@
// <atomic>
// template <class Integral>
// Integral
// atomic_fetch_add(volatile atomic<Integral>* obj, Integral op);
// template<class T>
// T
// atomic_fetch_add(volatile atomic<T>* obj, atomic<T>::difference_type) noexcept;
//
// template <class Integral>
// Integral
// atomic_fetch_add(atomic<Integral>* obj, Integral op);
//
// template <class T>
// T*
// atomic_fetch_add(volatile atomic<T>* obj, typename atomic<T>::difference_type) noexcept;
//
// template <class T>
// T*
// atomic_fetch_add(atomic<T*>* obj, typename atomic<T>::difference_type) noexcept;
// template<class T>
// T
// atomic_fetch_add(atomic<T>* obj, atomic<T>::difference_type) noexcept;
#include <atomic>
#include <type_traits>

View File

@ -10,21 +10,15 @@
// <atomic>
// template <class Integral>
// Integral
// atomic_fetch_add_explicit(volatile atomic<Integral>* obj, Integral op,
// memory_order m);
// template <class Integral>
// Integral
// atomic_fetch_add_explicit(atomic<Integral>* obj, Integral op,
// memory_order m);
// template <class T>
// T*
// atomic_fetch_add_explicit(volatile atomic<T*>* obj, ptrdiff_t op,
// memory_order m);
// template <class T>
// T*
// atomic_fetch_add_explicit(atomic<T*>* obj, ptrdiff_t op, memory_order m);
// template<class T>
// T
// atomic_fetch_add_explicit(volatile atomic<T>*, atomic<T>::difference_type,
// memory_order) noexcept;
//
// template<class T>
// T
// atomic_fetch_add_explicit(atomic<T>*, atomic<T>::difference_type,
// memory_order) noexcept;
#include <atomic>
#include <type_traits>

View File

@ -10,13 +10,13 @@
// <atomic>
// template <class Integral>
// Integral
// atomic_fetch_and(volatile atomic<Integral>* obj, Integral op);
// template<class T>
// T
// atomic_fetch_and(volatile atomic<T>*, atomic<T>::value_type) noexcept;
//
// template <class Integral>
// Integral
// atomic_fetch_and(atomic<Integral>* obj, Integral op);
// template<class T>
// T
// atomic_fetch_and(atomic<T>*, atomic<T>::value_type) noexcept;
#include <atomic>
#include <type_traits>
@ -33,12 +33,16 @@ struct TestFn {
A t(T(1));
assert(std::atomic_fetch_and(&t, T(2)) == T(1));
assert(t == T(0));
ASSERT_NOEXCEPT(std::atomic_fetch_and(&t, T(2)));
}
{
typedef std::atomic<T> A;
volatile A t(T(3));
assert(std::atomic_fetch_and(&t, T(2)) == T(3));
assert(t == T(2));
ASSERT_NOEXCEPT(std::atomic_fetch_and(&t, T(2)));
}
}
};

View File

@ -10,13 +10,15 @@
// <atomic>
// template <class Integral>
// Integral
// atomic_fetch_and_explicit(volatile atomic<Integral>* obj, Integral op);
// template<class T>
// T
// atomic_fetch_and_explicit(volatile atomic<T>*, atomic<T>::value_type,
// memory_order) noexcept;
//
// template <class Integral>
// Integral
// atomic_fetch_and_explicit(atomic<Integral>* obj, Integral op);
// template<class T>
// T
// atomic_fetch_and_explicit(atomic<T>*, atomic<T>::value_type,
// memory_order) noexcept;
#include <atomic>
#include <type_traits>
@ -34,6 +36,8 @@ struct TestFn {
assert(std::atomic_fetch_and_explicit(&t, T(2),
std::memory_order_seq_cst) == T(1));
assert(t == T(0));
ASSERT_NOEXCEPT(std::atomic_fetch_and_explicit(&t, T(2), std::memory_order_seq_cst));
}
{
typedef std::atomic<T> A;
@ -41,6 +45,8 @@ struct TestFn {
assert(std::atomic_fetch_and_explicit(&t, T(2),
std::memory_order_seq_cst) == T(3));
assert(t == T(2));
ASSERT_NOEXCEPT(std::atomic_fetch_and_explicit(&t, T(2), std::memory_order_seq_cst));
}
}
};

View File

@ -10,13 +10,13 @@
// <atomic>
// template <class Integral>
// Integral
// atomic_fetch_or(volatile atomic<Integral>* obj, Integral op);
// template<class T>
// T
// atomic_fetch_or(volatile atomic<T>*, atomic<T>::value_type) noexcept;
//
// template <class Integral>
// Integral
// atomic_fetch_or(atomic<Integral>* obj, Integral op);
// template<class T>
// T
// atomic_fetch_or(atomic<T>*, atomic<T>::value_type) noexcept;
#include <atomic>
#include <type_traits>
@ -33,12 +33,16 @@ struct TestFn {
A t(T(1));
assert(std::atomic_fetch_or(&t, T(2)) == T(1));
assert(t == T(3));
ASSERT_NOEXCEPT(std::atomic_fetch_or(&t, T(2)));
}
{
typedef std::atomic<T> A;
volatile A t(T(3));
assert(std::atomic_fetch_or(&t, T(2)) == T(3));
assert(t == T(3));
ASSERT_NOEXCEPT(std::atomic_fetch_or(&t, T(2)));
}
}
};

View File

@ -10,13 +10,15 @@
// <atomic>
// template <class Integral>
// Integral
// atomic_fetch_or_explicit(volatile atomic<Integral>* obj, Integral op);
// template<class T>
// T
// atomic_fetch_or_explicit(volatile atomic<T>*, atomic<T>::value_type,
// memory_order) noexcept;
//
// template <class Integral>
// Integral
// atomic_fetch_or_explicit(atomic<Integral>* obj, Integral op);
// template<class T>
// T
// atomic_fetch_or_explicit(atomic<T>*, atomic<T>::value_type,
// memory_order) noexcept;
#include <atomic>
#include <type_traits>
@ -34,6 +36,8 @@ struct TestFn {
assert(std::atomic_fetch_or_explicit(&t, T(2),
std::memory_order_seq_cst) == T(1));
assert(t == T(3));
ASSERT_NOEXCEPT(std::atomic_fetch_or_explicit(&t, T(2), std::memory_order_seq_cst));
}
{
typedef std::atomic<T> A;
@ -41,6 +45,8 @@ struct TestFn {
assert(std::atomic_fetch_or_explicit(&t, T(2),
std::memory_order_seq_cst) == T(3));
assert(t == T(3));
ASSERT_NOEXCEPT(std::atomic_fetch_or_explicit(&t, T(2), std::memory_order_seq_cst));
}
}
};

View File

@ -10,21 +10,13 @@
// <atomic>
// template <class Integral>
// Integral
// atomic_fetch_sub(volatile atomic<Integral>* obj, Integral op);
// template<class T>
// T
// atomic_fetch_sub(volatile atomic<T>*, atomic<T>::difference_type) noexcept;
//
// template <class Integral>
// Integral
// atomic_fetch_sub(atomic<Integral>* obj, Integral op);
//
// template <class T>
// T*
// atomic_fetch_sub(volatile atomic<T*>* obj, ptrdiff_t op);
//
// template <class T>
// T*
// atomic_fetch_sub(atomic<T*>* obj, ptrdiff_t op);
// template<class T>
// T
// atomic_fetch_sub(atomic<T>*, atomic<T>::difference_type) noexcept;
#include <atomic>
#include <type_traits>

View File

@ -10,22 +10,15 @@
// <atomic>
// template <class Integral>
// Integral
// atomic_fetch_sub_explicit(volatile atomic<Integral>* obj, Integral op,
// memory_order m);
// template <class Integral>
// Integral
// atomic_fetch_sub_explicit(atomic<Integral>* obj, Integral op,
// memory_order m);
// template<class T>
// T
// atomic_fetch_sub_explicit(volatile atomic<T>*, atomic<T>::difference_type,
// memory_order) noexcept;
//
// template <class T>
// T*
// atomic_fetch_sub_explicit(volatile atomic<T*>* obj, ptrdiff_t op,
// memory_order m);
// template <class T>
// T*
// atomic_fetch_sub_explicit(atomic<T*>* obj, ptrdiff_t op, memory_order m);
// template<class T>
// T
// atomic_fetch_sub_explicit(atomic<T>*, atomic<T>::difference_type,
// memory_order) noexcept;
#include <atomic>
#include <type_traits>

View File

@ -10,13 +10,13 @@
// <atomic>
// template <class Integral>
// Integral
// atomic_fetch_xor(volatile atomic<Integral>* obj, Integral op);
// template<class T>
// T
// atomic_fetch_xor(volatile atomic<T>*, atomic<T>::value_type) noexcept;
//
// template <class Integral>
// Integral
// atomic_fetch_xor(atomic<Integral>* obj, Integral op);
// template<class T>
// T
// atomic_fetch_xor(atomic<T>*, atomic<T>::value_type) noexcept;
#include <atomic>
#include <type_traits>
@ -33,12 +33,16 @@ struct TestFn {
A t(T(1));
assert(std::atomic_fetch_xor(&t, T(2)) == T(1));
assert(t == T(3));
ASSERT_NOEXCEPT(std::atomic_fetch_xor(&t, T(2)));
}
{
typedef std::atomic<T> A;
volatile A t(T(3));
assert(std::atomic_fetch_xor(&t, T(2)) == T(3));
assert(t == T(1));
ASSERT_NOEXCEPT(std::atomic_fetch_xor(&t, T(2)));
}
}
};

View File

@ -10,13 +10,15 @@
// <atomic>
// template <class Integral>
// Integral
// atomic_fetch_xor_explicit(volatile atomic<Integral>* obj, Integral op);
// template<class T>
// T
// atomic_fetch_xor_explicit(volatile atomic<T>*, atomic<T>::value_type,
// memory_order) noexcept;
//
// template <class Integral>
// Integral
// atomic_fetch_xor_explicit(atomic<Integral>* obj, Integral op);
// template<class T>
// T
// atomic_fetch_xor_explicit(atomic<T>*, atomic<T>::value_type,
// memory_order) noexcept;
#include <atomic>
#include <type_traits>
@ -34,6 +36,8 @@ struct TestFn {
assert(std::atomic_fetch_xor_explicit(&t, T(2),
std::memory_order_seq_cst) == T(1));
assert(t == T(3));
ASSERT_NOEXCEPT(std::atomic_fetch_xor_explicit(&t, T(2), std::memory_order_seq_cst));
}
{
typedef std::atomic<T> A;
@ -41,6 +45,8 @@ struct TestFn {
assert(std::atomic_fetch_xor_explicit(&t, T(2),
std::memory_order_seq_cst) == T(3));
assert(t == T(1));
ASSERT_NOEXCEPT(std::atomic_fetch_xor_explicit(&t, T(2), std::memory_order_seq_cst));
}
}
};

View File

@ -8,18 +8,17 @@
//
// UNSUPPORTED: libcpp-has-no-threads
// XFAIL: !non-lockfree-atomics
// ... assertion fails line 36
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
// <atomic>
// template <class T>
// void
// atomic_init(volatile atomic<T>* obj, T desr);
// atomic_init(volatile atomic<T>* obj, atomic<T>::value_type desr) noexcept;
//
// template <class T>
// void
// atomic_init(atomic<T>* obj, T desr);
// atomic_init(atomic<T>* obj, atomic<T>::value_type desr) noexcept;
#include <atomic>
#include <type_traits>
@ -38,6 +37,9 @@ struct TestFn {
volatile A vt;
std::atomic_init(&vt, T(2));
assert(vt == T(2));
ASSERT_NOEXCEPT(std::atomic_init(&t, T(1)));
ASSERT_NOEXCEPT(std::atomic_init(&vt, T(2)));
}
};

View File

@ -12,10 +12,10 @@
// <atomic>
// template <class T>
// bool atomic_is_lock_free(const volatile atomic<T>* obj);
// bool atomic_is_lock_free(const volatile atomic<T>* obj) noexcept;
//
// template <class T>
// bool atomic_is_lock_free(const atomic<T>* obj);
// bool atomic_is_lock_free(const atomic<T>* obj) noexcept;
#include <atomic>
#include <cassert>
@ -33,6 +33,9 @@ struct TestFn {
volatile A va(t);
bool b2 = std::atomic_is_lock_free(static_cast<const volatile A*>(&va));
assert(b1 == b2);
ASSERT_NOEXCEPT(std::atomic_is_lock_free(static_cast<const A*>(&a)));
ASSERT_NOEXCEPT(std::atomic_is_lock_free(static_cast<const volatile A*>(&va)));
}
};

View File

@ -8,17 +8,16 @@
//
// UNSUPPORTED: libcpp-has-no-threads
// XFAIL: !non-lockfree-atomics
// ... assertion fails line 35
// <atomic>
// template <class T>
// T
// atomic_load(const volatile atomic<T>* obj);
// atomic_load(const volatile atomic<T>*) noexcept;
//
// template <class T>
// T
// atomic_load(const atomic<T>* obj);
// atomic_load(const atomic<T>*) noexcept;
#include <atomic>
#include <type_traits>
@ -35,6 +34,9 @@ struct TestFn {
assert(std::atomic_load(&t) == T(1));
volatile A vt(T(2));
assert(std::atomic_load(&vt) == T(2));
ASSERT_NOEXCEPT(std::atomic_load(&t));
ASSERT_NOEXCEPT(std::atomic_load(&vt));
}
};

View File

@ -8,17 +8,16 @@
//
// UNSUPPORTED: libcpp-has-no-threads
// XFAIL: !non-lockfree-atomics
// ... assertion fails line 31
// <atomic>
// template <class T>
// T
// atomic_load_explicit(const volatile atomic<T>* obj, memory_order m);
// atomic_load_explicit(const volatile atomic<T>*, memory_order) noexcept;
//
// template <class T>
// T
// atomic_load_explicit(const atomic<T>* obj, memory_order m);
// atomic_load_explicit(const atomic<T>*, memory_order) noexcept;
#include <atomic>
#include <type_traits>
@ -35,6 +34,9 @@ struct TestFn {
assert(std::atomic_load_explicit(&t, std::memory_order_seq_cst) == T(1));
volatile A vt(T(2));
assert(std::atomic_load_explicit(&vt, std::memory_order_seq_cst) == T(2));
ASSERT_NOEXCEPT(std::atomic_load_explicit(&t, std::memory_order_seq_cst));
ASSERT_NOEXCEPT(std::atomic_load_explicit(&vt, std::memory_order_seq_cst));
}
};

View File

@ -13,11 +13,11 @@
// template <class T>
// void
// atomic_store(volatile atomic<T>* obj, T desr);
// atomic_store(volatile atomic<T>*, atomic<T>::value_type) noexcept;
//
// template <class T>
// void
// atomic_store(atomic<T>* obj, T desr);
// atomic_store(atomic<T>*, atomic<T>::value_type) noexcept;
#include <atomic>
#include <type_traits>
@ -36,6 +36,9 @@ struct TestFn {
volatile A vt;
std::atomic_store(&vt, T(2));
assert(vt == T(2));
ASSERT_NOEXCEPT(std::atomic_store(&t, T(1)));
ASSERT_NOEXCEPT(std::atomic_store(&vt, T(2)));
}
};

View File

@ -13,11 +13,13 @@
// template <class T>
// void
// atomic_store_explicit(volatile atomic<T>* obj, T desr, memory_order m);
// atomic_store_explicit(volatile atomic<T>*, atomic<T>::value_type,
// memory_order) noexcept;
//
// template <class T>
// void
// atomic_store_explicit(atomic<T>* obj, T desr, memory_order m);
// atomic_store_explicit(atomic<T>*, atomic<T>::value_type,
// memory_order) noexcept;
#include <atomic>
#include <type_traits>
@ -36,6 +38,9 @@ struct TestFn {
volatile A vt;
std::atomic_store_explicit(&vt, T(2), std::memory_order_seq_cst);
assert(vt == T(2));
ASSERT_NOEXCEPT(std::atomic_store_explicit(&t, T(1), std::memory_order_seq_cst));
ASSERT_NOEXCEPT(std::atomic_store_explicit(&vt, T(2), std::memory_order_seq_cst));
}
};

View File

@ -0,0 +1,80 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: libcpp-has-no-threads
// XFAIL: c++03
// XFAIL: !non-lockfree-atomics
// This test requires the dylib support introduced in D68480, which shipped in
// macOS 11.0.
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14|15}}
// <atomic>
// template<class T>
// void
// atomic_notify_all(volatile atomic<T>*);
//
// template<class T>
// void
// atomic_notify_all(atomic<T>*);
#include <atomic>
#include <type_traits>
#include <cassert>
#include <thread>
#include "make_test_thread.h"
#include "test_macros.h"
#include "atomic_helpers.h"
template <class T>
struct TestFn {
void operator()() const {
typedef std::atomic<T> A;
{
A a(T(1));
auto f = [&]() {
assert(std::atomic_load(&a) == T(1));
std::atomic_wait(&a, T(1));
assert(std::atomic_load(&a) == T(3));
};
std::thread t1 = support::make_test_thread(f);
std::thread t2 = support::make_test_thread(f);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::atomic_store(&a, T(3));
std::atomic_notify_all(&a);
t1.join();
t2.join();
}
{
volatile A a(T(2));
auto f = [&]() {
assert(std::atomic_load(&a) == T(2));
std::atomic_wait(&a, T(2));
assert(std::atomic_load(&a) == T(4));
};
std::thread t1 = support::make_test_thread(f);
std::thread t2 = support::make_test_thread(f);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::atomic_store(&a, T(4));
std::atomic_notify_all(&a);
t1.join();
t2.join();
}
}
};
int main(int, char**) {
TestEachAtomicType<TestFn>()();
return 0;
}

View File

@ -0,0 +1,68 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: libcpp-has-no-threads
// XFAIL: c++03
// XFAIL: !non-lockfree-atomics
// This test requires the dylib support introduced in D68480, which shipped in
// macOS 11.0.
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14|15}}
// <atomic>
// template<class T>
// void
// atomic_notify_one(volatile atomic<T>*);
//
// template<class T>
// void
// atomic_notify_one(atomic<T>*);
#include <atomic>
#include <type_traits>
#include <cassert>
#include <thread>
#include "make_test_thread.h"
#include "test_macros.h"
#include "atomic_helpers.h"
template <class T>
struct TestFn {
void operator()() const {
typedef std::atomic<T> A;
{
A a(T(1));
std::thread t = support::make_test_thread([&]() {
std::atomic_store(&a, T(3));
std::atomic_notify_one(&a);
});
std::atomic_wait(&a, T(1));
assert(std::atomic_load(&a) == T(3));
t.join();
}
{
volatile A a(T(2));
std::thread t = support::make_test_thread([&]() {
std::atomic_store(&a, T(4));
std::atomic_notify_one(&a);
});
std::atomic_wait(&a, T(2));
assert(std::atomic_load(&a) == T(4));
t.join();
}
}
};
int main(int, char**) {
TestEachAtomicType<TestFn>()();
return 0;
}

View File

@ -16,6 +16,14 @@
// <atomic>
// template<class T>
// void
// atomic_wait(const volatile atomic<T>*, atomic<T>::value_type);
//
// template<class T>
// void
// atomic_wait(const atomic<T>*, atomic<T>::value_type);
#include <atomic>
#include <type_traits>
#include <cassert>
@ -29,32 +37,35 @@ template <class T>
struct TestFn {
void operator()() const {
typedef std::atomic<T> A;
A t(T(1));
assert(std::atomic_load(&t) == T(1));
std::atomic_wait(&t, T(0));
std::thread t1 = support::make_test_thread([&](){
std::atomic_store(&t, T(3));
std::atomic_notify_one(&t);
});
std::atomic_wait(&t, T(1));
t1.join();
volatile A vt(T(2));
assert(std::atomic_load(&vt) == T(2));
std::atomic_wait(&vt, T(1));
std::thread t2 = support::make_test_thread([&](){
std::atomic_store(&vt, T(4));
std::atomic_notify_one(&vt);
});
std::atomic_wait(&vt, T(2));
t2.join();
{
A t(T(1));
assert(std::atomic_load(&t) == T(1));
std::atomic_wait(&t, T(0));
std::thread t1 = support::make_test_thread([&]() {
std::atomic_store(&t, T(3));
std::atomic_notify_one(&t);
});
std::atomic_wait(&t, T(1));
assert(std::atomic_load(&t) == T(3));
t1.join();
}
{
volatile A vt(T(2));
assert(std::atomic_load(&vt) == T(2));
std::atomic_wait(&vt, T(1));
std::thread t2 = support::make_test_thread([&]() {
std::atomic_store(&vt, T(4));
std::atomic_notify_one(&vt);
});
std::atomic_wait(&vt, T(2));
assert(std::atomic_load(&vt) == T(4));
t2.join();
}
}
};
int main(int, char**)
{
TestEachAtomicType<TestFn>()();
int main(int, char**) {
TestEachAtomicType<TestFn>()();
return 0;
}

View File

@ -0,0 +1,73 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: libcpp-has-no-threads
// XFAIL: c++03
// XFAIL: !non-lockfree-atomics
// This test requires the dylib support introduced in D68480, which shipped in
// macOS 11.0.
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14|15}}
// <atomic>
// template<class T>
// void
// atomic_wait_explicit(const volatile atomic<T>*, atomic<T>::value_type,
// memory_order);
//
// template<class T>
// void
// atomic_wait_explicit(const volatile atomic<T>*, atomic<T>::value_type,
// memory_order);
#include <atomic>
#include <type_traits>
#include <cassert>
#include <thread>
#include "make_test_thread.h"
#include "test_macros.h"
#include "atomic_helpers.h"
template <class T>
struct TestFn {
void operator()() const {
typedef std::atomic<T> A;
{
A t(T(1));
assert(std::atomic_load(&t) == T(1));
std::atomic_wait_explicit(&t, T(0), std::memory_order_seq_cst);
std::thread t1 = support::make_test_thread([&]() {
std::atomic_store(&t, T(3));
std::atomic_notify_one(&t);
});
std::atomic_wait_explicit(&t, T(1), std::memory_order_seq_cst);
assert(std::atomic_load(&t) == T(3));
t1.join();
}
{
volatile A vt(T(2));
assert(std::atomic_load(&vt) == T(2));
std::atomic_wait_explicit(&vt, T(1), std::memory_order_seq_cst);
std::thread t2 = support::make_test_thread([&]() {
std::atomic_store(&vt, T(4));
std::atomic_notify_one(&vt);
});
std::atomic_wait_explicit(&vt, T(2), std::memory_order_seq_cst);
assert(std::atomic_load(&vt) == T(4));
t2.join();
}
}
};
int main(int, char**) {
TestEachAtomicType<TestFn>()();
return 0;
}