brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.7 KiB · 90aa5ea Raw
225 lines · cpp
1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7 8// UNSUPPORTED: c++03, c++11, c++14, c++179// XFAIL: !has-64-bit-atomics10// XFAIL: !has-1024-bit-atomics11 12// MSVC warning C4310: cast truncates constant value13// ADDITIONAL_COMPILE_FLAGS(cl-style-warnings): /wd431014 15// bool compare_exchange_strong(T&, T, memory_order, memory_order) const noexcept;16// bool compare_exchange_strong(T&, T, memory_order = memory_order::seq_cst) const noexcept;17 18#include <atomic>19#include <cassert>20#include <concepts>21#include <type_traits>22 23#include "atomic_helpers.h"24#include "test_helper.h"25#include "test_macros.h"26 27template <typename T>28struct TestCompareExchangeStrong {29  void operator()() const {30    {31      T x(T(1));32      std::atomic_ref<T> const a(x);33 34      T t(T(1));35      std::same_as<bool> decltype(auto) y = a.compare_exchange_strong(t, T(2));36      assert(y == true);37      assert(a == T(2));38      assert(t == T(1));39      y = a.compare_exchange_strong(t, T(3));40      assert(y == false);41      assert(a == T(2));42      assert(t == T(2));43 44      ASSERT_NOEXCEPT(a.compare_exchange_strong(t, T(2)));45    }46    {47      T x(T(1));48      std::atomic_ref<T> const a(x);49 50      T t(T(1));51      std::same_as<bool> decltype(auto) y = a.compare_exchange_strong(t, T(2), std::memory_order_seq_cst);52      assert(y == true);53      assert(a == T(2));54      assert(t == T(1));55      y = a.compare_exchange_strong(t, T(3), std::memory_order_seq_cst);56      assert(y == false);57      assert(a == T(2));58      assert(t == T(2));59 60      ASSERT_NOEXCEPT(a.compare_exchange_strong(t, T(2), std::memory_order_seq_cst));61    }62    {63      T x(T(1));64      std::atomic_ref<T> const a(x);65 66      T t(T(1));67      std::same_as<bool> decltype(auto) y =68          a.compare_exchange_strong(t, T(2), std::memory_order_release, std::memory_order_relaxed);69      assert(y == true);70      assert(a == T(2));71      assert(t == T(1));72      y = a.compare_exchange_strong(t, T(3), std::memory_order_release, std::memory_order_relaxed);73      assert(y == false);74      assert(a == T(2));75      assert(t == T(2));76 77      ASSERT_NOEXCEPT(a.compare_exchange_strong(t, T(2), std::memory_order_release, std::memory_order_relaxed));78    }79 80    // success memory_order::release81    {82      auto store = [](std::atomic_ref<T> const& x, T old_val, T new_val) {83        auto r = x.compare_exchange_strong(old_val, new_val, std::memory_order::release, std::memory_order::relaxed);84        assert(r);85      };86 87      auto load = [](std::atomic_ref<T> const& x) { return x.load(std::memory_order::acquire); };88      test_acquire_release<T>(store, load);89 90      auto store_one_arg = [](std::atomic_ref<T> const& x, T old_val, T new_val) {91        auto r = x.compare_exchange_strong(old_val, new_val, std::memory_order::release);92        assert(r);93      };94      test_acquire_release<T>(store_one_arg, load);95    }96 97    // success memory_order::acquire98    {99      auto store = [](std::atomic_ref<T> const& x, T, T new_val) { x.store(new_val, std::memory_order::release); };100 101      auto load = [](std::atomic_ref<T> const& x) {102        auto val = x.load(std::memory_order::relaxed);103        while (!x.compare_exchange_strong(val, val, std::memory_order::acquire, std::memory_order::relaxed)) {104        }105        return val;106      };107      test_acquire_release<T>(store, load);108 109      auto load_one_arg = [](std::atomic_ref<T> const& x) {110        auto val = x.load(std::memory_order::relaxed);111        while (!x.compare_exchange_strong(val, val, std::memory_order::acquire)) {112        }113        return val;114      };115      test_acquire_release<T>(store, load_one_arg);116    }117 118    // success memory_order::acq_rel119    {120      auto store = [](std::atomic_ref<T> const& x, T old_val, T new_val) {121        auto r = x.compare_exchange_strong(old_val, new_val, std::memory_order::acq_rel, std::memory_order::relaxed);122        assert(r);123      };124      auto load = [](std::atomic_ref<T> const& x) {125        auto val = x.load(std::memory_order::relaxed);126        while (!x.compare_exchange_strong(val, val, std::memory_order::acq_rel, std::memory_order::relaxed)) {127        }128        return val;129      };130      test_acquire_release<T>(store, load);131 132      auto store_one_arg = [](std::atomic_ref<T> const& x, T old_val, T new_val) {133        auto r = x.compare_exchange_strong(old_val, new_val, std::memory_order::acq_rel);134        assert(r);135      };136      auto load_one_arg = [](std::atomic_ref<T> const& x) {137        auto val = x.load(std::memory_order::relaxed);138        while (!x.compare_exchange_strong(val, val, std::memory_order::acq_rel)) {139        }140        return val;141      };142      test_acquire_release<T>(store_one_arg, load_one_arg);143    }144 145    // success memory_order::seq_cst146    {147      auto store = [](std::atomic_ref<T> const& x, T old_val, T new_val) {148        auto r = x.compare_exchange_strong(old_val, new_val, std::memory_order::seq_cst, std::memory_order::relaxed);149        assert(r);150      };151      auto load = [](std::atomic_ref<T> const& x) {152        auto val = x.load(std::memory_order::relaxed);153        while (!x.compare_exchange_strong(val, val, std::memory_order::seq_cst, std::memory_order::relaxed)) {154        }155        return val;156      };157      test_seq_cst<T>(store, load);158 159      auto store_one_arg = [](std::atomic_ref<T> const& x, T old_val, T new_val) {160        auto r = x.compare_exchange_strong(old_val, new_val, std::memory_order::seq_cst);161        assert(r);162      };163      auto load_one_arg = [](std::atomic_ref<T> const& x) {164        auto val = x.load(std::memory_order::relaxed);165        while (!x.compare_exchange_strong(val, val, std::memory_order::seq_cst)) {166        }167        return val;168      };169      test_seq_cst<T>(store_one_arg, load_one_arg);170    }171 172    // failure memory_order::acquire173    {174      auto store = [](std::atomic_ref<T> const& x, T, T new_val) { x.store(new_val, std::memory_order::release); };175      auto load  = [](std::atomic_ref<T> const& x) {176        auto result = x.load(std::memory_order::relaxed);177        T unexpected(T(255));178        bool r =179            x.compare_exchange_strong(unexpected, unexpected, std::memory_order::relaxed, std::memory_order::acquire);180        assert(!r);181        return result;182      };183      test_acquire_release<T>(store, load);184 185      auto load_one_arg = [](std::atomic_ref<T> const& x) {186        auto result = x.load(std::memory_order::relaxed);187        T unexpected(T(255));188        bool r = x.compare_exchange_strong(unexpected, unexpected, std::memory_order::acquire);189        assert(!r);190        return result;191      };192      test_acquire_release<T>(store, load_one_arg);193 194      // acq_rel replaced by acquire195      auto load_one_arg_acq_rel = [](std::atomic_ref<T> const& x) {196        auto result = x.load(std::memory_order::relaxed);197        T unexpected(T(255));198        bool r = x.compare_exchange_strong(unexpected, unexpected, std::memory_order::acq_rel);199        assert(!r);200        return result;201      };202      test_acquire_release<T>(store, load_one_arg_acq_rel);203    }204 205    // failure memory_order::seq_cst206    {207      auto store = [](std::atomic_ref<T> const& x, T, T new_val) { x.store(new_val, std::memory_order::seq_cst); };208      auto load  = [](std::atomic_ref<T> const& x) {209        auto result = x.load(std::memory_order::relaxed);210        T unexpected(T(255));211        bool r =212            x.compare_exchange_strong(unexpected, unexpected, std::memory_order::relaxed, std::memory_order::seq_cst);213        assert(!r);214        return result;215      };216      test_seq_cst<T>(store, load);217    }218  }219};220 221int main(int, char**) {222  TestEachAtomicType<TestCompareExchangeStrong>()();223  return 0;224}225