brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.5 KiB · ab89ebd Raw
116 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: target={{x86_64-.*}} && tsan11 12// integral-type fetch_sub(integral-type, memory_order = memory_order::seq_cst) const noexcept;13// floating-point-type fetch_sub(floating-point-type, memory_order = memory_order::seq_cst) const noexcept;14// T* fetch_sub(difference_type, memory_order = memory_order::seq_cst) const noexcept;15 16#include <atomic>17#include <cassert>18#include <concepts>19#include <type_traits>20#include <utility>21 22#include "atomic_helpers.h"23#include "test_helper.h"24#include "test_macros.h"25 26template <typename T>27concept has_fetch_sub = requires {28  std::declval<T const>().fetch_sub(std::declval<T>());29  std::declval<T const>().fetch_sub(std::declval<T>(), std::declval<std::memory_order>());30};31 32template <typename T>33struct TestDoesNotHaveFetchSub {34  void operator()() const { static_assert(!has_fetch_sub<std::atomic_ref<T>>); }35};36 37template <typename T>38struct TestFetchSub {39  void operator()() const {40    if constexpr (std::is_arithmetic_v<T>) {41      T x(T(7));42      std::atomic_ref<T> const a(x);43 44      {45        std::same_as<T> decltype(auto) y = a.fetch_sub(T(4));46        assert(y == T(7));47        assert(x == T(3));48        ASSERT_NOEXCEPT(a.fetch_sub(T(0)));49      }50 51      {52        std::same_as<T> decltype(auto) y = a.fetch_sub(T(2), std::memory_order_relaxed);53        assert(y == T(3));54        assert(x == T(1));55        ASSERT_NOEXCEPT(a.fetch_sub(T(0), std::memory_order_relaxed));56      }57    } else if constexpr (std::is_pointer_v<T>) {58      using U = std::remove_pointer_t<T>;59      U t[9]  = {};60      T p{&t[7]};61      std::atomic_ref<T> const a(p);62 63      {64        std::same_as<T> decltype(auto) y = a.fetch_sub(4);65        assert(y == &t[7]);66        assert(a == &t[3]);67        ASSERT_NOEXCEPT(a.fetch_sub(0));68      }69 70      {71        std::same_as<T> decltype(auto) y = a.fetch_sub(2, std::memory_order_relaxed);72        assert(y == &t[3]);73        assert(a == &t[1]);74        ASSERT_NOEXCEPT(a.fetch_sub(0, std::memory_order_relaxed));75      }76    } else {77      static_assert(std::is_void_v<T>);78    }79 80    // memory_order::release81    {82      auto fetch_sub = [](std::atomic_ref<T> const& x, T old_val, T new_val) {83        x.fetch_sub(old_val - new_val, std::memory_order::release);84      };85      auto load = [](std::atomic_ref<T> const& x) { return x.load(std::memory_order::acquire); };86      test_acquire_release<T>(fetch_sub, load);87    }88 89    // memory_order::seq_cst90    {91      auto fetch_sub_no_arg = [](std::atomic_ref<T> const& x, T old_val, T new_val) { x.fetch_sub(old_val - new_val); };92      auto fetch_sub_with_order = [](std::atomic_ref<T> const& x, T old_val, T new_val) {93        x.fetch_sub(old_val - new_val, std::memory_order::seq_cst);94      };95      auto load = [](std::atomic_ref<T> const& x) { return x.load(); };96      test_seq_cst<T>(fetch_sub_no_arg, load);97      test_seq_cst<T>(fetch_sub_with_order, load);98    }99  }100};101 102int main(int, char**) {103  TestEachIntegralType<TestFetchSub>()();104 105  TestFetchSub<float>()();106  TestFetchSub<double>()();107 108  TestEachPointerType<TestFetchSub>()();109 110  TestDoesNotHaveFetchSub<bool>()();111  TestDoesNotHaveFetchSub<UserAtomicType>()();112  TestDoesNotHaveFetchSub<LargeUserAtomicType>()();113 114  return 0;115}116