diff --git a/libcxx/docs/Status/Cxx17Papers.csv b/libcxx/docs/Status/Cxx17Papers.csv --- a/libcxx/docs/Status/Cxx17Papers.csv +++ b/libcxx/docs/Status/Cxx17Papers.csv @@ -101,7 +101,7 @@ "`P0518R1 `__","LWG","Allowing copies as arguments to function objects given to parallel algorithms in response to CH11","Kona","","" "`P0523R1 `__","LWG","Wording for CH 10: Complexity of parallel algorithms","Kona","","" "`P0548R1 `__","LWG","common_type and duration","Kona","|Complete|","5.0" -"`P0558R1 `__","LWG","Resolving atomic named base class inconsistencies","Kona","","" +"`P0558R1 `__","LWG","Resolving atomic named base class inconsistencies","Kona","|Complete|","" "`P0574R1 `__","LWG","Algorithm Complexity Constraints and Parallel Overloads","Kona","","" "`P0599R1 `__","LWG","noexcept for hash functions","Kona","|Complete|","5.0" "`P0604R0 `__","LWG","Resolving GB 55, US 84, US 85, US 86","Kona","|Complete|","" diff --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv --- a/libcxx/docs/Status/Cxx20Issues.csv +++ b/libcxx/docs/Status/Cxx20Issues.csv @@ -34,7 +34,7 @@ "`2980 `__","Cannot compare_exchange empty pointers","Albuquerque","","" "`2981 `__","Remove redundant deduction guides from standard library","Albuquerque","","" "`2982 `__","Making size_type consistent in associative container deduction guides","Albuquerque","","" -"`2988 `__","Clause 32 cleanup missed one typename","Albuquerque","","" +"`2988 `__","Clause 32 cleanup missed one typename","Albuquerque","|Complete|","13.0" "`2993 `__","reference_wrapper conversion from T&&","Albuquerque","|Complete|","13.0" "`2998 `__","Requirements on function objects passed to {``forward_``,}list-specific algorithms","Albuquerque","|Nothing To Do|","" "`3001 `__","weak_ptr::element_type needs remove_extent_t","Albuquerque","","" diff --git a/libcxx/include/atomic b/libcxx/include/atomic --- a/libcxx/include/atomic +++ b/libcxx/include/atomic @@ -263,196 +263,145 @@ }; -template - bool atomic_is_lock_free(const volatile atomic* obj) noexcept; - -template - bool atomic_is_lock_free(const atomic* obj) noexcept; - -template - void atomic_store(volatile atomic* obj, T desr) noexcept; - -template - void atomic_store(atomic* obj, T desr) noexcept; - -template - void atomic_store_explicit(volatile atomic* obj, T desr, memory_order m) noexcept; - -template - void atomic_store_explicit(atomic* obj, T desr, memory_order m) noexcept; - -template - T atomic_load(const volatile atomic* obj) noexcept; - -template - T atomic_load(const atomic* obj) noexcept; - -template - T atomic_load_explicit(const volatile atomic* obj, memory_order m) noexcept; - -template - T atomic_load_explicit(const atomic* obj, memory_order m) noexcept; - -template - T atomic_exchange(volatile atomic* obj, T desr) noexcept; - -template - T atomic_exchange(atomic* obj, T desr) noexcept; - -template - T atomic_exchange_explicit(volatile atomic* obj, T desr, memory_order m) noexcept; - -template - T atomic_exchange_explicit(atomic* obj, T desr, memory_order m) noexcept; - -template - bool atomic_compare_exchange_weak(volatile atomic* obj, T* expc, T desr) noexcept; - -template - bool atomic_compare_exchange_weak(atomic* obj, T* expc, T desr) noexcept; - -template - bool atomic_compare_exchange_strong(volatile atomic* obj, T* expc, T desr) noexcept; - -template - bool atomic_compare_exchange_strong(atomic* obj, T* expc, T desr) noexcept; - -template - bool atomic_compare_exchange_weak_explicit(volatile atomic* obj, T* expc, - T desr, - memory_order s, memory_order f) noexcept; - -template - bool atomic_compare_exchange_weak_explicit(atomic* obj, T* expc, T desr, - memory_order s, memory_order f) noexcept; - -template - bool atomic_compare_exchange_strong_explicit(volatile atomic* obj, - T* expc, T desr, - memory_order s, memory_order f) noexcept; - -template - bool atomic_compare_exchange_strong_explicit(atomic* obj, T* expc, - T desr, - memory_order s, memory_order f) noexcept; - -template - void atomic_wait(const volatile atomic* obj, T old) noexcept; - -template - void atomic_wait(const atomic* obj, T old) noexcept; - -template - void atomic_wait_explicit(const volatile atomic* obj, T old, memory_order m) noexcept; - -template - void atomic_wait_explicit(const atomic* obj, T old, memory_order m) noexcept; - -template - void atomic_one(volatile atomic* obj) noexcept; - -template - void atomic_one(atomic* obj) noexcept; - -template - void atomic_all(volatile atomic* obj) noexcept; - -template - void atomic_all(atomic* obj) noexcept; - -template - Integral atomic_fetch_add(volatile atomic* obj, Integral op) noexcept; - -template - Integral atomic_fetch_add(atomic* obj, Integral op) noexcept; - -template - Integral atomic_fetch_add_explicit(volatile atomic* obj, Integral op, - memory_order m) noexcept; -template - Integral atomic_fetch_add_explicit(atomic* obj, Integral op, - memory_order m) noexcept; -template - Integral atomic_fetch_sub(volatile atomic* obj, Integral op) noexcept; - -template - Integral atomic_fetch_sub(atomic* obj, Integral op) noexcept; - -template - Integral atomic_fetch_sub_explicit(volatile atomic* obj, Integral op, - memory_order m) noexcept; - -template - Integral atomic_fetch_sub_explicit(atomic* obj, Integral op, - memory_order m) noexcept; - -template - Integral atomic_fetch_and(volatile atomic* obj, Integral op) noexcept; - -template - Integral atomic_fetch_and(atomic* obj, Integral op) noexcept; - -template - Integral atomic_fetch_and_explicit(volatile atomic* obj, Integral op, - memory_order m) noexcept; - -template - Integral atomic_fetch_and_explicit(atomic* obj, Integral op, - memory_order m) noexcept; - -template - Integral atomic_fetch_or(volatile atomic* obj, Integral op) noexcept; - -template - Integral atomic_fetch_or(atomic* obj, Integral op) noexcept; - -template - Integral atomic_fetch_or_explicit(volatile atomic* obj, Integral op, - memory_order m) noexcept; - -template - Integral atomic_fetch_or_explicit(atomic* obj, Integral op, - memory_order m) noexcept; - -template - Integral atomic_fetch_xor(volatile atomic* obj, Integral op) noexcept; - -template - Integral atomic_fetch_xor(atomic* obj, Integral op) noexcept; - -template - Integral atomic_fetch_xor_explicit(volatile atomic* obj, Integral op, - memory_order m) noexcept; - -template - Integral atomic_fetch_xor_explicit(atomic* obj, Integral op, - memory_order m) noexcept; - -template - T* atomic_fetch_add(volatile atomic* obj, ptrdiff_t op) noexcept; - -template - T* atomic_fetch_add(atomic* obj, ptrdiff_t op) noexcept; - -template - T* atomic_fetch_add_explicit(volatile atomic* obj, ptrdiff_t op, - memory_order m) noexcept; - -template - T* atomic_fetch_add_explicit(atomic* obj, ptrdiff_t op, memory_order m) noexcept; - -template - T* atomic_fetch_sub(volatile atomic* obj, ptrdiff_t op) noexcept; - -template - T* atomic_fetch_sub(atomic* obj, ptrdiff_t op) noexcept; - -template - T* atomic_fetch_sub_explicit(volatile atomic* obj, ptrdiff_t op, - memory_order m) noexcept; - -template - T* atomic_fetch_sub_explicit(atomic* obj, ptrdiff_t op, memory_order m) noexcept; +// [atomics.nonmembers], non-member functions +template + bool atomic_is_lock_free(const volatile atomic*) noexcept; +template + bool atomic_is_lock_free(const atomic*) noexcept; +template + void atomic_store(volatile atomic*, typename atomic::value_type) noexcept; +template + void atomic_store(atomic*, typename atomic::value_type) noexcept; +template + void atomic_store_explicit(volatile atomic*, typename atomic::value_type, + memory_order) noexcept; +template + void atomic_store_explicit(atomic*, typename atomic::value_type, + memory_order) noexcept; +template + T atomic_load(const volatile atomic*) noexcept; +template + T atomic_load(const atomic*) noexcept; +template + T atomic_load_explicit(const volatile atomic*, memory_order) noexcept; +template + T atomic_load_explicit(const atomic*, memory_order) noexcept; +template + T atomic_exchange(volatile atomic*, typename atomic::value_type) noexcept; +template + T atomic_exchange(atomic*, typename atomic::value_type) noexcept; +template + T atomic_exchange_explicit(volatile atomic*, typename atomic::value_type, + memory_order) noexcept; +template + T atomic_exchange_explicit(atomic*, typename atomic::value_type, + memory_order) noexcept; +template + bool atomic_compare_exchange_weak(volatile atomic*, + typename atomic::value_type*, + typename atomic::value_type) noexcept; +template + bool atomic_compare_exchange_weak(atomic*, + typename atomic::value_type*, + typename atomic::value_type) noexcept; +template + bool atomic_compare_exchange_strong(volatile atomic*, + typename atomic::value_type*, + typename atomic::value_type) noexcept; +template + bool atomic_compare_exchange_strong(atomic*, + typename atomic::value_type*, + typename atomic::value_type) noexcept; +template + bool atomic_compare_exchange_weak_explicit(volatile atomic*, + typename atomic::value_type*, + typename atomic::value_type, + memory_order, memory_order) noexcept; +template + bool atomic_compare_exchange_weak_explicit(atomic*, + typename atomic::value_type*, + typename atomic::value_type, + memory_order, memory_order) noexcept; +template + bool atomic_compare_exchange_strong_explicit(volatile atomic*, + typename atomic::value_type*, + typename atomic::value_type, + memory_order, memory_order) noexcept; +template + bool atomic_compare_exchange_strong_explicit(atomic*, + typename atomic::value_type*, + typename atomic::value_type, + memory_order, memory_order) noexcept; + +template + T atomic_fetch_add(volatile atomic*, typename atomic::difference_type) noexcept; +template + T atomic_fetch_add(atomic*, typename atomic::difference_type) noexcept; +template + T atomic_fetch_add_explicit(volatile atomic*, typename atomic::difference_type, + memory_order) noexcept; +template + T atomic_fetch_add_explicit(atomic*, typename atomic::difference_type, + memory_order) noexcept; +template + T atomic_fetch_sub(volatile atomic*, typename atomic::difference_type) noexcept; +template + T atomic_fetch_sub(atomic*, typename atomic::difference_type) noexcept; +template + T atomic_fetch_sub_explicit(volatile atomic*, typename atomic::difference_type, + memory_order) noexcept; +template + T atomic_fetch_sub_explicit(atomic*, typename atomic::difference_type, + memory_order) noexcept; +template + T atomic_fetch_and(volatile atomic*, typename atomic::value_type) noexcept; +template + T atomic_fetch_and(atomic*, typename atomic::value_type) noexcept; +template + T atomic_fetch_and_explicit(volatile atomic*, typename atomic::value_type, + memory_order) noexcept; +template + T atomic_fetch_and_explicit(atomic*, typename atomic::value_type, + memory_order) noexcept; +template + T atomic_fetch_or(volatile atomic*, typename atomic::value_type) noexcept; +template + T atomic_fetch_or(atomic*, typename atomic::value_type) noexcept; +template + T atomic_fetch_or_explicit(volatile atomic*, typename atomic::value_type, + memory_order) noexcept; +template + T atomic_fetch_or_explicit(atomic*, typename atomic::value_type, + memory_order) noexcept; +template + T atomic_fetch_xor(volatile atomic*, typename atomic::value_type) noexcept; +template + T atomic_fetch_xor(atomic*, typename atomic::value_type) noexcept; +template + T atomic_fetch_xor_explicit(volatile atomic*, typename atomic::value_type, + memory_order) noexcept; +template + T atomic_fetch_xor_explicit(atomic*, typename atomic::value_type, + memory_order) noexcept; + +template + void atomic_wait(const volatile atomic*, typename atomic::value_type); +template + void atomic_wait(const atomic*, typename atomic::value_type); +template + void atomic_wait_explicit(const volatile atomic*, typename atomic::value_type, + memory_order); +template + void atomic_wait_explicit(const atomic*, typename atomic::value_type, + memory_order); +template + void atomic_notify_one(volatile atomic*); +template + void atomic_notify_one(atomic*); +template + void atomic_notify_all(volatile atomic*); +template + void atomic_notify_all(atomic*); // Atomics for standard typedef types diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong.pass.cpp @@ -8,17 +8,20 @@ // // UNSUPPORTED: libcpp-has-no-threads // XFAIL: !non-lockfree-atomics -// ... assertion fails line 34 // // template // bool -// atomic_compare_exchange_strong(volatile atomic* obj, T* expc, T desr); +// atomic_compare_exchange_strong(volatile atomic*, +// typename atomic::value_type*, +// typename atomic::value_type) noexcept; // // template // bool -// atomic_compare_exchange_strong(atomic* obj, T* expc, T desr); +// atomic_compare_exchange_strong(atomic*, +// typename atomic::value_type*, +// typename atomic::value_type) noexcept; #include #include @@ -40,6 +43,8 @@ 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 A; @@ -51,6 +56,8 @@ 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))); } } }; diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong_explicit.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_strong_explicit.pass.cpp @@ -8,20 +8,22 @@ // // UNSUPPORTED: libcpp-has-no-threads // XFAIL: !non-lockfree-atomics -// ... assertion fails line 38 // // template // bool -// atomic_compare_exchange_strong_explicit(volatile atomic* obj, T* expc, -// T desr, -// memory_order s, memory_order f); +// atomic_compare_exchange_strong_explicit(volatile atomic*, +// typename atomic::value_type*, +// typename atomic::value_type, +// memory_order, memory_order) noexcept; // // template // bool -// atomic_compare_exchange_strong_explicit(atomic* obj, T* expc, T desr, -// memory_order s, memory_order f); +// atomic_compare_exchange_strong_explicit(atomic*, +// typename atomic::value_type*, +// typename atomic::value_type, +// memory_order, memory_order) noexcept; #include #include @@ -45,6 +47,9 @@ 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 A; @@ -58,6 +63,9 @@ 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)); } } }; diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak.pass.cpp @@ -8,17 +8,20 @@ // // UNSUPPORTED: libcpp-has-no-threads // XFAIL: !non-lockfree-atomics -// ... assertion fails line 34 // // template // bool -// atomic_compare_exchange_weak(volatile atomic* obj, T* expc, T desr); +// atomic_compare_exchange_weak(volatile atomic*, +// typename atomic::value_type*, +// typename atomic::value_type) noexcept; // // template // bool -// atomic_compare_exchange_weak(atomic* obj, T* expc, T desr); +// atomic_compare_exchange_weak(atomic*, +// typename atomic::value_type*, +// typename atomic::value_type) noexcept; #include #include @@ -41,6 +44,8 @@ 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 A; @@ -52,6 +57,8 @@ 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))); } } }; diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak_explicit.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_compare_exchange_weak_explicit.pass.cpp @@ -8,20 +8,22 @@ // // UNSUPPORTED: libcpp-has-no-threads // XFAIL: !non-lockfree-atomics -// ... assertion fails line 38 // // template // bool -// atomic_compare_exchange_weak_explicit(volatile atomic* obj, T* expc, -// T desr, -// memory_order s, memory_order f); +// atomic_compare_exchange_weak_explicit(volatile atomic*, +// typename atomic::value_type*, +// typename atomic::value_type, +// memory_order, memory_order) noexcept; // // template // bool -// atomic_compare_exchange_weak_explicit(atomic* obj, T* expc, T desr, -// memory_order s, memory_order f); +// atomic_compare_exchange_weak_explicit(atomic*, +// typename atomic::value_type*, +// typename atomic::value_type, +// memory_order, memory_order) noexcept; #include #include @@ -47,6 +49,9 @@ 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 A; @@ -60,6 +65,9 @@ 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)); } } }; diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange.pass.cpp @@ -8,17 +8,16 @@ // // UNSUPPORTED: libcpp-has-no-threads // XFAIL: !non-lockfree-atomics -// ... fails assertion line 31 // // template // T -// atomic_exchange(volatile atomic* obj, T desr); +// atomic_exchange(volatile atomic*, typename atomic::value_type) noexcept; // // template // T -// atomic_exchange(atomic* obj, T desr); +// atomic_exchange(atomic*, typename atomic::value_type) noexcept; #include #include @@ -37,6 +36,9 @@ 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))); } }; diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange_explicit.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_exchange_explicit.pass.cpp @@ -8,17 +8,18 @@ // // UNSUPPORTED: libcpp-has-no-threads // XFAIL: !non-lockfree-atomics -// ... assertion fails line 32 // // template // T -// atomic_exchange_explicit(volatile atomic* obj, T desr, memory_order m); +// atomic_exchange_explicit(volatile atomic*, typename atomic::value_type, +// memory_order) noexcept; // // template // T -// atomic_exchange_explicit(atomic* obj, T desr, memory_order m); +// atomic_exchange_explicit(atomic*, typename atomic::value_type, +// memory_order) noexcept; #include #include @@ -39,6 +40,9 @@ 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)); } }; diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_add.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_add.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_add.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_add.pass.cpp @@ -10,21 +10,13 @@ // -// template -// Integral -// atomic_fetch_add(volatile atomic* obj, Integral op); -// -// template -// Integral -// atomic_fetch_add(atomic* obj, Integral op); -// -// template -// T* +// template +// T // atomic_fetch_add(volatile atomic* obj, typename atomic::difference_type) noexcept; // -// template -// T* -// atomic_fetch_add(atomic* obj, typename atomic::difference_type) noexcept; +// template +// T +// atomic_fetch_add(atomic* obj, typename atomic::difference_type) noexcept; #include #include diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_add_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_add_explicit.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_add_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_add_explicit.pass.cpp @@ -10,21 +10,15 @@ // -// template -// Integral -// atomic_fetch_add_explicit(volatile atomic* obj, Integral op, -// memory_order m); -// template -// Integral -// atomic_fetch_add_explicit(atomic* obj, Integral op, -// memory_order m); -// template -// T* -// atomic_fetch_add_explicit(volatile atomic* obj, ptrdiff_t op, -// memory_order m); -// template -// T* -// atomic_fetch_add_explicit(atomic* obj, ptrdiff_t op, memory_order m); +// template +// T +// atomic_fetch_add_explicit(volatile atomic*, typename atomic::difference_type, +// memory_order) noexcept; +// +// template +// T +// atomic_fetch_add_explicit(atomic*, typename atomic::difference_type, +// memory_order) noexcept; #include #include diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_and.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_and.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_and.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_and.pass.cpp @@ -10,13 +10,13 @@ // -// template -// Integral -// atomic_fetch_and(volatile atomic* obj, Integral op); +// template +// T +// atomic_fetch_and(volatile atomic*, typename atomic::value_type) noexcept; // -// template -// Integral -// atomic_fetch_and(atomic* obj, Integral op); +// template +// T +// atomic_fetch_and(atomic*, typename atomic::value_type) noexcept; #include #include @@ -33,12 +33,16 @@ 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 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))); } } }; diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_and_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_and_explicit.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_and_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_and_explicit.pass.cpp @@ -10,13 +10,15 @@ // -// template -// Integral -// atomic_fetch_and_explicit(volatile atomic* obj, Integral op); +// template +// T +// atomic_fetch_and_explicit(volatile atomic*, typename atomic::value_type, +// memory_order) noexcept; // -// template -// Integral -// atomic_fetch_and_explicit(atomic* obj, Integral op); +// template +// T +// atomic_fetch_and_explicit(atomic*, typename atomic::value_type, +// memory_order) noexcept; #include #include @@ -34,6 +36,8 @@ 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 A; @@ -41,6 +45,8 @@ 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)); } } }; diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_or.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_or.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_or.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_or.pass.cpp @@ -10,13 +10,13 @@ // -// template -// Integral -// atomic_fetch_or(volatile atomic* obj, Integral op); +// template +// T +// atomic_fetch_or(volatile atomic*, typename atomic::value_type) noexcept; // -// template -// Integral -// atomic_fetch_or(atomic* obj, Integral op); +// template +// T +// atomic_fetch_or(atomic*, typename atomic::value_type) noexcept; #include #include @@ -33,12 +33,16 @@ 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 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))); } } }; diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_or_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_or_explicit.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_or_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_or_explicit.pass.cpp @@ -10,13 +10,15 @@ // -// template -// Integral -// atomic_fetch_or_explicit(volatile atomic* obj, Integral op); +// template +// T +// atomic_fetch_or_explicit(volatile atomic*, typename atomic::value_type, +// memory_order) noexcept; // -// template -// Integral -// atomic_fetch_or_explicit(atomic* obj, Integral op); +// template +// T +// atomic_fetch_or_explicit(atomic*, typename atomic::value_type, +// memory_order) noexcept; #include #include @@ -34,6 +36,8 @@ 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 A; @@ -41,6 +45,8 @@ 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)); } } }; diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_sub.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_sub.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_sub.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_sub.pass.cpp @@ -10,21 +10,13 @@ // -// template -// Integral -// atomic_fetch_sub(volatile atomic* obj, Integral op); +// template +// T +// atomic_fetch_sub(volatile atomic*, typename atomic::difference_type) noexcept; // -// template -// Integral -// atomic_fetch_sub(atomic* obj, Integral op); -// -// template -// T* -// atomic_fetch_sub(volatile atomic* obj, ptrdiff_t op); -// -// template -// T* -// atomic_fetch_sub(atomic* obj, ptrdiff_t op); +// template +// T +// atomic_fetch_sub(atomic*, typename atomic::difference_type) noexcept; #include #include diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_sub_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_sub_explicit.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_sub_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_sub_explicit.pass.cpp @@ -10,22 +10,15 @@ // -// template -// Integral -// atomic_fetch_sub_explicit(volatile atomic* obj, Integral op, -// memory_order m); -// template -// Integral -// atomic_fetch_sub_explicit(atomic* obj, Integral op, -// memory_order m); +// template +// T +// atomic_fetch_sub_explicit(volatile atomic*, typename atomic::difference_type, +// memory_order) noexcept; // -// template -// T* -// atomic_fetch_sub_explicit(volatile atomic* obj, ptrdiff_t op, -// memory_order m); -// template -// T* -// atomic_fetch_sub_explicit(atomic* obj, ptrdiff_t op, memory_order m); +// template +// T +// atomic_fetch_sub_explicit(atomic*, typename atomic::difference_type, +// memory_order) noexcept; #include #include diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_xor.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_xor.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_xor.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_xor.pass.cpp @@ -10,13 +10,13 @@ // -// template -// Integral -// atomic_fetch_xor(volatile atomic* obj, Integral op); +// template +// T +// atomic_fetch_xor(volatile atomic*, typename atomic::value_type) noexcept; // -// template -// Integral -// atomic_fetch_xor(atomic* obj, Integral op); +// template +// T +// atomic_fetch_xor(atomic*, typename atomic::value_type) noexcept; #include #include @@ -33,12 +33,16 @@ 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 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))); } } }; diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_xor_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_xor_explicit.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_xor_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_fetch_xor_explicit.pass.cpp @@ -10,13 +10,15 @@ // -// template -// Integral -// atomic_fetch_xor_explicit(volatile atomic* obj, Integral op); +// template +// T +// atomic_fetch_xor_explicit(volatile atomic*, typename atomic::value_type, +// memory_order) noexcept; // -// template -// Integral -// atomic_fetch_xor_explicit(atomic* obj, Integral op); +// template +// T +// atomic_fetch_xor_explicit(atomic*, typename atomic::value_type, +// memory_order) noexcept; #include #include @@ -34,6 +36,8 @@ 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 A; @@ -41,6 +45,8 @@ 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)); } } }; diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_init.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_init.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_init.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_init.pass.cpp @@ -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 // // template // void -// atomic_init(volatile atomic* obj, T desr); +// atomic_init(volatile atomic* obj, typename atomic::value_type desr) noexcept; // // template // void -// atomic_init(atomic* obj, T desr); +// atomic_init(atomic* obj, typename atomic::value_type desr) noexcept; #include #include @@ -38,6 +37,9 @@ 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))); } }; diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_is_lock_free.pass.cpp @@ -12,10 +12,10 @@ // // template -// bool atomic_is_lock_free(const volatile atomic* obj); +// bool atomic_is_lock_free(const volatile atomic* obj) noexcept; // // template -// bool atomic_is_lock_free(const atomic* obj); +// bool atomic_is_lock_free(const atomic* obj) noexcept; #include #include @@ -33,6 +33,9 @@ volatile A va(t); bool b2 = std::atomic_is_lock_free(static_cast(&va)); assert(b1 == b2); + + ASSERT_NOEXCEPT(std::atomic_is_lock_free(static_cast(&a))); + ASSERT_NOEXCEPT(std::atomic_is_lock_free(static_cast(&va))); } }; diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load.pass.cpp @@ -8,17 +8,16 @@ // // UNSUPPORTED: libcpp-has-no-threads // XFAIL: !non-lockfree-atomics -// ... assertion fails line 35 // // template // T -// atomic_load(const volatile atomic* obj); +// atomic_load(const volatile atomic*) noexcept; // // template // T -// atomic_load(const atomic* obj); +// atomic_load(const atomic*) noexcept; #include #include @@ -35,6 +34,9 @@ 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)); } }; diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load_explicit.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_load_explicit.pass.cpp @@ -8,17 +8,16 @@ // // UNSUPPORTED: libcpp-has-no-threads // XFAIL: !non-lockfree-atomics -// ... assertion fails line 31 // // template // T -// atomic_load_explicit(const volatile atomic* obj, memory_order m); +// atomic_load_explicit(const volatile atomic*, memory_order) noexcept; // // template // T -// atomic_load_explicit(const atomic* obj, memory_order m); +// atomic_load_explicit(const atomic*, memory_order) noexcept; #include #include @@ -35,6 +34,9 @@ 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)); } }; diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_store.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_store.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_store.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_store.pass.cpp @@ -13,11 +13,11 @@ // template // void -// atomic_store(volatile atomic* obj, T desr); +// atomic_store(volatile atomic*, typename atomic::value_type) noexcept; // // template // void -// atomic_store(atomic* obj, T desr); +// atomic_store(atomic*, typename atomic::value_type) noexcept; #include #include @@ -36,6 +36,9 @@ 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))); } }; diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_store_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_store_explicit.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_store_explicit.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.req/atomic_store_explicit.pass.cpp @@ -13,11 +13,13 @@ // template // void -// atomic_store_explicit(volatile atomic* obj, T desr, memory_order m); +// atomic_store_explicit(volatile atomic*, typename atomic::value_type, +// memory_order) noexcept; // // template // void -// atomic_store_explicit(atomic* obj, T desr, memory_order m); +// atomic_store_explicit(atomic*, typename atomic::value_type, +// memory_order) noexcept; #include #include @@ -36,6 +38,9 @@ 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)); } }; diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_notify_all.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_notify_all.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_notify_all.pass.cpp @@ -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}} + +// + +// template +// void +// atomic_notify_all(volatile atomic*); +// +// template +// void +// atomic_notify_all(atomic*); + +#include +#include +#include +#include + +#include "make_test_thread.h" +#include "test_macros.h" +#include "atomic_helpers.h" + +template +struct TestFn { + void operator()() const { + typedef std::atomic 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()(); + + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_notify_one.pass.cpp copy from libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait.pass.cpp copy to libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_notify_one.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_notify_one.pass.cpp @@ -16,6 +16,14 @@ // +// template +// void +// atomic_notify_one(volatile atomic*); +// +// template +// void +// atomic_notify_one(atomic*); + #include #include #include @@ -30,31 +38,31 @@ void operator()() const { typedef std::atomic 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 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()(); +int main(int, char**) { + TestEachAtomicType()(); return 0; } diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait.pass.cpp --- a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait.pass.cpp +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait.pass.cpp @@ -16,6 +16,14 @@ // +// template +// void +// atomic_wait(const volatile atomic*, typename atomic::value_type); +// +// template +// void +// atomic_wait(const atomic*, typename atomic::value_type); + #include #include #include @@ -29,32 +37,35 @@ struct TestFn { void operator()() const { typedef std::atomic 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()(); +int main(int, char**) { + TestEachAtomicType()(); return 0; } diff --git a/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait_explicit.pass.cpp b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait_explicit.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait_explicit.pass.cpp @@ -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}} + +// + +// template +// void +// atomic_wait_explicit(const volatile atomic*, typename atomic::value_type, +// memory_order); +// +// template +// void +// atomic_wait_explicit(const volatile atomic*, typename atomic::value_type, +// memory_order); + +#include +#include +#include +#include + +#include "make_test_thread.h" +#include "test_macros.h" +#include "atomic_helpers.h" + +template +struct TestFn { + void operator()() const { + typedef std::atomic 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()(); + + return 0; +}