brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.9 KiB · 99c1385 Raw
230 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_weak(T&, T, memory_order, memory_order) const noexcept;16// bool compare_exchange_weak(T&, T, memory_order = memory_order::seq_cst) const noexcept;17 18#include <atomic>19#include <concepts>20#include <cassert>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 TestCompareExchangeWeak {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_weak(t, T(2));36      assert(y == true);37      assert(a == T(2));38      assert(t == T(1));39      y = a.compare_exchange_weak(t, T(3));40      assert(y == false);41      assert(a == T(2));42      assert(t == T(2));43 44      ASSERT_NOEXCEPT(a.compare_exchange_weak(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_weak(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_weak(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_weak(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_weak(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_weak(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_weak(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        // could fail spuriously, so put it in a loop84        while (!x.compare_exchange_weak(old_val, new_val, std::memory_order::release, std::memory_order::relaxed)) {85        }86      };87 88      auto load = [](std::atomic_ref<T> const& x) { return x.load(std::memory_order::acquire); };89      test_acquire_release<T>(store, load);90 91      auto store_one_arg = [](std::atomic_ref<T> const& x, T old_val, T new_val) {92        // could fail spuriously, so put it in a loop93        while (!x.compare_exchange_weak(old_val, new_val, std::memory_order::release)) {94        }95      };96      test_acquire_release<T>(store_one_arg, load);97    }98 99    // success memory_order::acquire100    {101      auto store = [](std::atomic_ref<T> const& x, T, T new_val) { x.store(new_val, std::memory_order::release); };102      auto load  = [](std::atomic_ref<T> const& x) {103        auto val = x.load(std::memory_order::relaxed);104        while (!x.compare_exchange_weak(val, val, std::memory_order::acquire, std::memory_order::relaxed)) {105        }106        return val;107      };108      test_acquire_release<T>(store, load);109 110      auto load_one_arg = [](std::atomic_ref<T> const& x) {111        auto val = x.load(std::memory_order::relaxed);112        while (!x.compare_exchange_weak(val, val, std::memory_order::acquire)) {113        }114        return val;115      };116      test_acquire_release<T>(store, load_one_arg);117    }118 119    // success memory_order::acq_rel120    {121      auto store = [](std::atomic_ref<T> const& x, T old_val, T new_val) {122        // could fail spuriously, so put it in a loop123        while (!x.compare_exchange_weak(old_val, new_val, std::memory_order::acq_rel, std::memory_order::relaxed)) {124        }125      };126      auto load = [](std::atomic_ref<T> const& x) {127        auto val = x.load(std::memory_order::relaxed);128        while (!x.compare_exchange_weak(val, val, std::memory_order::acq_rel, std::memory_order::relaxed)) {129        }130        return val;131      };132      test_acquire_release<T>(store, load);133 134      auto store_one_arg = [](std::atomic_ref<T> const& x, T old_val, T new_val) {135        // could fail spuriously, so put it in a loop136        while (!x.compare_exchange_weak(old_val, new_val, std::memory_order::acq_rel)) {137        }138      };139      auto load_one_arg = [](std::atomic_ref<T> const& x) {140        auto val = x.load(std::memory_order::relaxed);141        while (!x.compare_exchange_weak(val, val, std::memory_order::acq_rel)) {142        }143        return val;144      };145      test_acquire_release<T>(store_one_arg, load_one_arg);146    }147 148    // success memory_order::seq_cst149    {150      auto store = [](std::atomic_ref<T> const& x, T old_val, T new_val) {151        // could fail spuriously, so put it in a loop152        while (!x.compare_exchange_weak(old_val, new_val, std::memory_order::seq_cst, std::memory_order::relaxed)) {153        }154      };155      auto load = [](std::atomic_ref<T> const& x) {156        auto val = x.load(std::memory_order::relaxed);157        while (!x.compare_exchange_weak(val, val, std::memory_order::seq_cst, std::memory_order::relaxed)) {158        }159        return val;160      };161      test_seq_cst<T>(store, load);162 163      auto store_one_arg = [](std::atomic_ref<T> const& x, T old_val, T new_val) {164        // could fail spuriously, so put it in a loop165        while (!x.compare_exchange_weak(old_val, new_val, std::memory_order::seq_cst)) {166        }167      };168      auto load_one_arg = [](std::atomic_ref<T> const& x) {169        auto val = x.load(std::memory_order::relaxed);170        while (!x.compare_exchange_weak(val, val, std::memory_order::seq_cst)) {171        }172        return val;173      };174      test_seq_cst<T>(store_one_arg, load_one_arg);175    }176 177    // failure memory_order::acquire178    {179      auto store = [](std::atomic_ref<T> const& x, T, T new_val) { x.store(new_val, std::memory_order::release); };180      auto load  = [](std::atomic_ref<T> const& x) {181        auto result = x.load(std::memory_order::relaxed);182        T unexpected(T(255));183        bool r =184            x.compare_exchange_weak(unexpected, unexpected, std::memory_order::relaxed, std::memory_order::acquire);185        assert(!r);186        return result;187      };188      test_acquire_release<T>(store, load);189 190      auto load_one_arg = [](std::atomic_ref<T> const& x) {191        auto result = x.load(std::memory_order::relaxed);192        T unexpected(T(255));193        bool r = x.compare_exchange_weak(unexpected, unexpected, std::memory_order::acquire);194        assert(!r);195        return result;196      };197      test_acquire_release<T>(store, load_one_arg);198 199      // acq_rel replaced by acquire200      auto load_one_arg_acq_rel = [](std::atomic_ref<T> const& x) {201        auto result = x.load(std::memory_order::relaxed);202        T unexpected(T(255));203        bool r = x.compare_exchange_weak(unexpected, unexpected, std::memory_order::acq_rel);204        assert(!r);205        return result;206      };207      test_acquire_release<T>(store, load_one_arg_acq_rel);208    }209 210    // failure memory_order::seq_cst211    {212      auto store = [](std::atomic_ref<T> const& x, T, T new_val) { x.store(new_val, std::memory_order::seq_cst); };213      auto load  = [](std::atomic_ref<T> const& x) {214        auto result = x.load(std::memory_order::relaxed);215        T unexpected(T(255));216        bool r =217            x.compare_exchange_weak(unexpected, unexpected, std::memory_order::relaxed, std::memory_order::seq_cst);218        assert(!r);219        return result;220      };221      test_seq_cst<T>(store, load);222    }223  }224};225 226int main(int, char**) {227  TestEachAtomicType<TestCompareExchangeWeak>()();228  return 0;229}230