(root)/
gcc-13.2.0/
libstdc++-v3/
testsuite/
20_util/
weak_ptr/
atomic_weak_ptr.cc
// { 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 <memory>
#include <thread>
#include <testsuite_hooks.h>

// Check constexpr constructor.
constinit std::atomic<std::weak_ptr<int>> a;

void
test_is_lock_free()
{
  using test_type = std::atomic<std::weak_ptr<int>>;
  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<A>( 0, 42 );
  using ptr_t = std::weak_ptr<A>;
  ptr_t wa{ a };
  {
    std::atomic<ptr_t> p{ };
    VERIFY( p.load().lock().get() == nullptr );
  }

  std::atomic<ptr_t> p{ wa };
  VERIFY( p.load().lock().get() == a.get() );

  auto b = std::make_shared<A>( 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<std::weak_ptr<int>> p;
  std::weak_ptr<int> a = std::make_shared<int>();
  std::weak_ptr<int> b = std::make_shared<int>();

  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();
}