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