1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8// UNSUPPORTED: c++03, c++11, c++14, c++17
9// XFAIL: !has-64-bit-atomics
10
11// T exchange(T, memory_order = memory_order::seq_cst) volatile noexcept;
12// T exchange(T, memory_order = memory_order::seq_cst) noexcept;
13
14#include <atomic>
15#include <cassert>
16#include <concepts>
17#include <type_traits>
18#include <utility>
19
20#include "test_helper.h"
21#include "test_macros.h"
22
23template <class T>
24concept HasVolatileExchange = requires(volatile std::atomic<T>& a, T t) { a.exchange(t); };
25
26template <class T, template <class> class MaybeVolatile = std::type_identity_t>
27void test_impl() {
28 // Uncomment the test after P1831R1 is implemented
29 // static_assert(HasVolatileExchange<T> == std::atomic<T>::is_always_lock_free);
30 static_assert(noexcept(std::declval<MaybeVolatile<std::atomic<T>>&>() = (T(0))));
31
32 // exchange
33 {
34 MaybeVolatile<std::atomic<T>> a(T(3.1));
35 std::same_as<T> decltype(auto) r = a.exchange(T(1.2), std::memory_order::relaxed);
36 assert(a.load() == T(1.2));
37 assert(r == T(3.1));
38 }
39
40 // memory_order::release
41 {
42 auto exchange = [](MaybeVolatile<std::atomic<T>>& x, T, T new_val) {
43 x.exchange(new_val, std::memory_order::release);
44 };
45 auto load = [](MaybeVolatile<std::atomic<T>>& x) { return x.load(std::memory_order::acquire); };
46 test_acquire_release<T, MaybeVolatile>(exchange, load);
47 }
48
49 // memory_order::seq_cst
50 {
51 auto exchange_no_arg = [](MaybeVolatile<std::atomic<T>>& x, T, T new_val) { x.exchange(new_val); };
52 auto exchange_with_order = [](MaybeVolatile<std::atomic<T>>& x, T, T new_val) {
53 x.exchange(new_val, std::memory_order::seq_cst);
54 };
55 auto load = [](MaybeVolatile<std::atomic<T>>& x) { return x.load(); };
56 test_seq_cst<T, MaybeVolatile>(exchange_no_arg, load);
57 test_seq_cst<T, MaybeVolatile>(exchange_with_order, load);
58 }
59}
60
61template <class T>
62void test() {
63 test_impl<T>();
64 if constexpr (std::atomic<T>::is_always_lock_free) {
65 test_impl<T, std::add_volatile_t>();
66 }
67}
68
69int main(int, char**) {
70 test<float>();
71 test<double>();
72 // TODO https://github.com/llvm/llvm-project/issues/47978
73 // test<long double>();
74
75 return 0;
76}
77

source code of libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/exchange.pass.cpp