// { dg-options "-std=gnu++20" } // { dg-do run { target c++20 } } // { dg-require-effective-target gthreads } // { dg-additional-options "-pthread" { target pthread } } // { dg-add-options libatomic } #include #include #include // Check constexpr constructor. constinit std::atomic> a; void test_is_lock_free() { using test_type = std::atomic>; static_assert( test_type::is_always_lock_free == false ); test_type p; VERIFY( p.is_lock_free() == false ); } void test_atomic_weak_ptr() { struct A { int a; int b; }; auto a = std::make_shared( 0, 42 ); using ptr_t = std::weak_ptr; ptr_t wa{ a }; { std::atomic p{ }; VERIFY( p.load().lock().get() == nullptr ); } std::atomic p{ wa }; VERIFY( p.load().lock().get() == a.get() ); auto b = std::make_shared( 42, 0 ); ptr_t wb{ b }; p.store(wb); VERIFY( p.load().lock().get() != a.get() ); VERIFY( p.load().lock().get() == b.get() ); p.exchange(wa); VERIFY( p.load().lock().get() != b.get() ); VERIFY( p.load().lock().get() == a.get() ); { ptr_t aa{ a }; VERIFY( p.compare_exchange_strong(aa, b, std::memory_order_seq_cst, std::memory_order_seq_cst) == true ); ptr_t bb{ a }; VERIFY( p.compare_exchange_strong(bb, b, std::memory_order_seq_cst, std::memory_order_seq_cst) == false ); VERIFY( bb.lock().get() == b.get() ); } { ptr_t bb{ b }; VERIFY( p.compare_exchange_weak(bb, a, std::memory_order_seq_cst, std::memory_order_seq_cst) == true ); ptr_t aa{ b }; VERIFY( p.compare_exchange_weak(aa, a, std::memory_order_seq_cst, std::memory_order_seq_cst) == false ); VERIFY( aa.lock().get() == a.get() ); } } void test_wait_notify() { std::atomic> p; std::weak_ptr a = std::make_shared(); std::weak_ptr b = std::make_shared(); p.store(a); p.wait(b); std::thread t([&] { p.store(b); p.notify_one(); }); p.wait(a); t.join(); } int main() { test_is_lock_free(); test_atomic_weak_ptr(); test_wait_notify(); }