xref: /llvm-project/libcxx/test/std/atomics/atomics.ref/exchange.pass.cpp (revision fbd2365c467ba5c28d65451cfffcbf563df2c647)
142ba740aSDamien L-G //
242ba740aSDamien L-G // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
342ba740aSDamien L-G // See https://llvm.org/LICENSE.txt for license information.
442ba740aSDamien L-G // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
542ba740aSDamien L-G //
642ba740aSDamien L-G //===----------------------------------------------------------------------===//
742ba740aSDamien L-G 
842ba740aSDamien L-G // UNSUPPORTED: c++03, c++11, c++14, c++17
942ba740aSDamien L-G // XFAIL: !has-64-bit-atomics
1042ba740aSDamien L-G // XFAIL: !has-1024-bit-atomics
1142ba740aSDamien L-G 
1242ba740aSDamien L-G // T exchange(T, memory_order = memory_order::seq_cst) const noexcept;
1342ba740aSDamien L-G 
1442ba740aSDamien L-G #include <atomic>
1542ba740aSDamien L-G #include <cassert>
1642ba740aSDamien L-G #include <concepts>
1742ba740aSDamien L-G #include <type_traits>
1842ba740aSDamien L-G 
1942ba740aSDamien L-G #include "atomic_helpers.h"
20*fbd2365cSDamien L-G #include "test_helper.h"
2142ba740aSDamien L-G #include "test_macros.h"
2242ba740aSDamien L-G 
2342ba740aSDamien L-G template <typename T>
2442ba740aSDamien L-G struct TestExchange {
2542ba740aSDamien L-G   void operator()() const {
26*fbd2365cSDamien L-G     {
2742ba740aSDamien L-G       T x(T(1));
2842ba740aSDamien L-G       std::atomic_ref<T> const a(x);
2942ba740aSDamien L-G 
3042ba740aSDamien L-G       {
3142ba740aSDamien L-G         std::same_as<T> decltype(auto) y = a.exchange(T(2));
3242ba740aSDamien L-G         assert(y == T(1));
3342ba740aSDamien L-G         ASSERT_NOEXCEPT(a.exchange(T(2)));
3442ba740aSDamien L-G       }
3542ba740aSDamien L-G 
3642ba740aSDamien L-G       {
3742ba740aSDamien L-G         std::same_as<T> decltype(auto) y = a.exchange(T(3), std::memory_order_seq_cst);
3842ba740aSDamien L-G         assert(y == T(2));
3942ba740aSDamien L-G         ASSERT_NOEXCEPT(a.exchange(T(3), std::memory_order_seq_cst));
4042ba740aSDamien L-G       }
4142ba740aSDamien L-G     }
42*fbd2365cSDamien L-G 
43*fbd2365cSDamien L-G     // memory_order::release
44*fbd2365cSDamien L-G     {
45*fbd2365cSDamien L-G       auto exchange = [](std::atomic_ref<T> const& x, T, T new_val) {
46*fbd2365cSDamien L-G         x.exchange(new_val, std::memory_order::release);
47*fbd2365cSDamien L-G       };
48*fbd2365cSDamien L-G       auto load = [](std::atomic_ref<T> const& x) { return x.load(std::memory_order::acquire); };
49*fbd2365cSDamien L-G       test_acquire_release<T>(exchange, load);
50*fbd2365cSDamien L-G     }
51*fbd2365cSDamien L-G 
52*fbd2365cSDamien L-G     // memory_order::seq_cst
53*fbd2365cSDamien L-G     {
54*fbd2365cSDamien L-G       auto exchange_no_arg     = [](std::atomic_ref<T> const& x, T, T new_val) { x.exchange(new_val); };
55*fbd2365cSDamien L-G       auto exchange_with_order = [](std::atomic_ref<T> const& x, T, T new_val) {
56*fbd2365cSDamien L-G         x.exchange(new_val, std::memory_order::seq_cst);
57*fbd2365cSDamien L-G       };
58*fbd2365cSDamien L-G       auto load = [](std::atomic_ref<T> const& x) { return x.load(); };
59*fbd2365cSDamien L-G       test_seq_cst<T>(exchange_no_arg, load);
60*fbd2365cSDamien L-G       test_seq_cst<T>(exchange_with_order, load);
61*fbd2365cSDamien L-G     }
62*fbd2365cSDamien L-G   }
6342ba740aSDamien L-G };
6442ba740aSDamien L-G 
6542ba740aSDamien L-G int main(int, char**) {
6642ba740aSDamien L-G   TestEachAtomicType<TestExchange>()();
6742ba740aSDamien L-G   return 0;
6842ba740aSDamien L-G }
69