Implement P0943R6 Supporting C Atomics In C++ (#2008)

Co-authored-by: Stephan T. Lavavej <stl@nuwen.net>
This commit is contained in:
Adam Bucior 2021-08-17 02:52:46 +02:00 коммит произвёл GitHub
Родитель 46477a1152
Коммит 0680fabf17
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
10 изменённых файлов: 273 добавлений и 0 удалений

Просмотреть файл

@ -184,6 +184,7 @@ set(HEADERS
${CMAKE_CURRENT_LIST_DIR}/inc/span
${CMAKE_CURRENT_LIST_DIR}/inc/sstream
${CMAKE_CURRENT_LIST_DIR}/inc/stack
${CMAKE_CURRENT_LIST_DIR}/inc/stdatomic.h
${CMAKE_CURRENT_LIST_DIR}/inc/stdexcept
${CMAKE_CURRENT_LIST_DIR}/inc/stop_token
${CMAKE_CURRENT_LIST_DIR}/inc/streambuf

Просмотреть файл

@ -138,6 +138,7 @@
#include <barrier>
#include <latch>
#include <semaphore>
#include <stdatomic.h>
#include <stop_token>
#endif // _M_CEE_PURE

Просмотреть файл

@ -94,6 +94,7 @@
"span",
"sstream",
"stack",
"stdatomic.h",
"stdexcept",
"stop_token",
"streambuf",

131
stl/inc/stdatomic.h Normal file
Просмотреть файл

@ -0,0 +1,131 @@
// stdatomic.h standard header
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#pragma once
#ifndef _STDATOMIC_H_
#define _STDATOMIC_H_
#include <yvals.h>
#if _STL_COMPILER_PREPROCESSOR
#ifdef _M_CEE_PURE
#error <stdatomic.h> is not supported when compiling with /clr:pure.
#endif // _M_CEE_PURE
#if !_HAS_CXX23
#pragma message("The contents of <stdatomic.h> are available only with C++23 or later.")
#else // ^^^ !_HAS_CXX23 / _HAS_CXX23 vvv
#include <atomic>
#pragma pack(push, _CRT_PACKING)
#pragma warning(push, _STL_WARNING_LEVEL)
#pragma warning(disable : _STL_DISABLED_WARNINGS)
_STL_DISABLE_CLANG_WARNINGS
#pragma push_macro("new")
#undef new
template <class _Ty>
using _Std_atomic = _STD atomic<_Ty>;
#define _Atomic(T) _Std_atomic<T>
// clang-format off
using _STD memory_order;
using _STD memory_order_relaxed;
using _STD memory_order_consume;
using _STD memory_order_acquire;
using _STD memory_order_release;
using _STD memory_order_acq_rel;
using _STD memory_order_seq_cst;
using _STD atomic_flag;
using _STD atomic_bool;
using _STD atomic_char;
using _STD atomic_schar;
using _STD atomic_uchar;
using _STD atomic_short;
using _STD atomic_ushort;
using _STD atomic_int;
using _STD atomic_uint;
using _STD atomic_long;
using _STD atomic_ulong;
using _STD atomic_llong;
using _STD atomic_ullong;
#ifdef __cpp_lib_char8_t
using _STD atomic_char8_t;
#endif // __cpp_lib_char8_t
using _STD atomic_char16_t;
using _STD atomic_char32_t;
using _STD atomic_wchar_t;
using _STD atomic_int8_t;
using _STD atomic_uint8_t;
using _STD atomic_int16_t;
using _STD atomic_uint16_t;
using _STD atomic_int32_t;
using _STD atomic_uint32_t;
using _STD atomic_int64_t;
using _STD atomic_uint64_t;
using _STD atomic_int_least8_t;
using _STD atomic_uint_least8_t;
using _STD atomic_int_least16_t;
using _STD atomic_uint_least16_t;
using _STD atomic_int_least32_t;
using _STD atomic_uint_least32_t;
using _STD atomic_int_least64_t;
using _STD atomic_uint_least64_t;
using _STD atomic_int_fast8_t;
using _STD atomic_uint_fast8_t;
using _STD atomic_int_fast16_t;
using _STD atomic_uint_fast16_t;
using _STD atomic_int_fast32_t;
using _STD atomic_uint_fast32_t;
using _STD atomic_int_fast64_t;
using _STD atomic_uint_fast64_t;
using _STD atomic_intptr_t;
using _STD atomic_uintptr_t;
using _STD atomic_size_t;
using _STD atomic_ptrdiff_t;
using _STD atomic_intmax_t;
using _STD atomic_uintmax_t;
using _STD atomic_is_lock_free;
using _STD atomic_load;
using _STD atomic_load_explicit;
using _STD atomic_store;
using _STD atomic_store_explicit;
using _STD atomic_exchange;
using _STD atomic_exchange_explicit;
using _STD atomic_compare_exchange_strong;
using _STD atomic_compare_exchange_strong_explicit;
using _STD atomic_compare_exchange_weak;
using _STD atomic_compare_exchange_weak_explicit;
using _STD atomic_fetch_add;
using _STD atomic_fetch_add_explicit;
using _STD atomic_fetch_sub;
using _STD atomic_fetch_sub_explicit;
using _STD atomic_fetch_or;
using _STD atomic_fetch_or_explicit;
using _STD atomic_fetch_and;
using _STD atomic_fetch_and_explicit;
using _STD atomic_flag_test_and_set;
using _STD atomic_flag_test_and_set_explicit;
using _STD atomic_flag_clear;
using _STD atomic_flag_clear_explicit;
using _STD atomic_thread_fence;
using _STD atomic_signal_fence;
// clang-format on
#pragma pop_macro("new")
_STL_RESTORE_CLANG_WARNINGS
#pragma warning(pop)
#pragma pack(pop)
#endif // ^^^ _HAS_CXX23 ^^^
#endif // _STL_COMPILER_PREPROCESSOR
#endif // _STDATOMIC_H_

Просмотреть файл

@ -263,6 +263,7 @@
// _HAS_CXX23 directly controls:
// P0401R6 Providing Size Feedback In The Allocator Interface
// P0943R6 Supporting C Atomics In C++
// P1048R1 is_scoped_enum
// P1132R7 out_ptr(), inout_ptr()
// P1425R4 Iterator Pair Constructors For stack And queue
@ -1365,6 +1366,7 @@
#define __cpp_lib_out_ptr 202106L
#endif // __cpp_lib_concepts
#define __cpp_lib_stdatomic_h 202011L
#define __cpp_lib_string_contains 202011L
#define __cpp_lib_to_underlying 202102L
#endif // _HAS_CXX23

Просмотреть файл

@ -405,6 +405,7 @@ tests\P0898R3_concepts
tests\P0898R3_identity
tests\P0912R5_coroutine
tests\P0919R3_heterogeneous_unordered_lookup
tests\P0943R6_stdatomic_h
tests\P0966R1_string_reserve_should_not_shrink
tests\P0980R1_constexpr_strings
tests\P1004R2_constexpr_vector

Просмотреть файл

@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
RUNALL_INCLUDE ..\usual_latest_matrix.lst

Просмотреть файл

@ -0,0 +1,117 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include <stdatomic.h>
static_assert(ATOMIC_BOOL_LOCK_FREE == 2);
static_assert(ATOMIC_CHAR_LOCK_FREE == 2);
static_assert(ATOMIC_CHAR16_T_LOCK_FREE == 2);
static_assert(ATOMIC_CHAR32_T_LOCK_FREE == 2);
static_assert(ATOMIC_WCHAR_T_LOCK_FREE == 2);
static_assert(ATOMIC_SHORT_LOCK_FREE == 2);
static_assert(ATOMIC_INT_LOCK_FREE == 2);
static_assert(ATOMIC_LONG_LOCK_FREE == 2);
static_assert(ATOMIC_LLONG_LOCK_FREE == 2);
static_assert(ATOMIC_POINTER_LOCK_FREE == 2);
#include <atomic>
#include <type_traits>
using std::is_same_v;
static_assert(is_same_v<_Atomic(int), std::atomic<int>>);
static_assert(is_same_v<_Atomic(unsigned int), std::atomic<unsigned int>>);
static_assert(is_same_v<_Atomic(float), std::atomic<float>>);
static_assert(is_same_v<_Atomic(char), std::atomic<char>>);
static_assert(is_same_v<std::memory_order, memory_order>);
static_assert(std::memory_order_relaxed == memory_order_relaxed);
static_assert(std::memory_order_consume == memory_order_consume);
static_assert(std::memory_order_acquire == memory_order_acquire);
static_assert(std::memory_order_release == memory_order_release);
static_assert(std::memory_order_acq_rel == memory_order_acq_rel);
static_assert(std::memory_order_seq_cst == memory_order_seq_cst);
static_assert(is_same_v<std::atomic_flag, atomic_flag>);
static_assert(is_same_v<std::atomic_bool, atomic_bool>);
static_assert(is_same_v<std::atomic_char, atomic_char>);
static_assert(is_same_v<std::atomic_schar, atomic_schar>);
static_assert(is_same_v<std::atomic_uchar, atomic_uchar>);
static_assert(is_same_v<std::atomic_short, atomic_short>);
static_assert(is_same_v<std::atomic_ushort, atomic_ushort>);
static_assert(is_same_v<std::atomic_int, atomic_int>);
static_assert(is_same_v<std::atomic_uint, atomic_uint>);
static_assert(is_same_v<std::atomic_long, atomic_long>);
static_assert(is_same_v<std::atomic_ulong, atomic_ulong>);
static_assert(is_same_v<std::atomic_llong, atomic_llong>);
static_assert(is_same_v<std::atomic_ullong, atomic_ullong>);
#ifdef __cpp_lib_char8_t
static_assert(is_same_v<std::atomic_char8_t, atomic_char8_t>);
#endif // __cpp_lib_char8_t
static_assert(is_same_v<std::atomic_char16_t, atomic_char16_t>);
static_assert(is_same_v<std::atomic_char32_t, atomic_char32_t>);
static_assert(is_same_v<std::atomic_wchar_t, atomic_wchar_t>);
static_assert(is_same_v<std::atomic_int8_t, atomic_int8_t>);
static_assert(is_same_v<std::atomic_uint8_t, atomic_uint8_t>);
static_assert(is_same_v<std::atomic_int16_t, atomic_int16_t>);
static_assert(is_same_v<std::atomic_uint16_t, atomic_uint16_t>);
static_assert(is_same_v<std::atomic_int32_t, atomic_int32_t>);
static_assert(is_same_v<std::atomic_uint32_t, atomic_uint32_t>);
static_assert(is_same_v<std::atomic_int64_t, atomic_int64_t>);
static_assert(is_same_v<std::atomic_uint64_t, atomic_uint64_t>);
static_assert(is_same_v<std::atomic_int_least8_t, atomic_int_least8_t>);
static_assert(is_same_v<std::atomic_uint_least8_t, atomic_uint_least8_t>);
static_assert(is_same_v<std::atomic_int_least16_t, atomic_int_least16_t>);
static_assert(is_same_v<std::atomic_uint_least16_t, atomic_uint_least16_t>);
static_assert(is_same_v<std::atomic_int_least32_t, atomic_int_least32_t>);
static_assert(is_same_v<std::atomic_uint_least32_t, atomic_uint_least32_t>);
static_assert(is_same_v<std::atomic_int_least64_t, atomic_int_least64_t>);
static_assert(is_same_v<std::atomic_uint_least64_t, atomic_uint_least64_t>);
static_assert(is_same_v<std::atomic_int_fast8_t, atomic_int_fast8_t>);
static_assert(is_same_v<std::atomic_uint_fast8_t, atomic_uint_fast8_t>);
static_assert(is_same_v<std::atomic_int_fast16_t, atomic_int_fast16_t>);
static_assert(is_same_v<std::atomic_uint_fast16_t, atomic_uint_fast16_t>);
static_assert(is_same_v<std::atomic_int_fast32_t, atomic_int_fast32_t>);
static_assert(is_same_v<std::atomic_uint_fast32_t, atomic_uint_fast32_t>);
static_assert(is_same_v<std::atomic_int_fast64_t, atomic_int_fast64_t>);
static_assert(is_same_v<std::atomic_uint_fast64_t, atomic_uint_fast64_t>);
static_assert(is_same_v<std::atomic_intptr_t, atomic_intptr_t>);
static_assert(is_same_v<std::atomic_uintptr_t, atomic_uintptr_t>);
static_assert(is_same_v<std::atomic_size_t, atomic_size_t>);
static_assert(is_same_v<std::atomic_ptrdiff_t, atomic_ptrdiff_t>);
static_assert(is_same_v<std::atomic_intmax_t, atomic_intmax_t>);
static_assert(is_same_v<std::atomic_uintmax_t, atomic_uintmax_t>);
namespace test {
using ::atomic_compare_exchange_strong;
using ::atomic_compare_exchange_strong_explicit;
using ::atomic_compare_exchange_weak;
using ::atomic_compare_exchange_weak_explicit;
using ::atomic_exchange;
using ::atomic_exchange_explicit;
using ::atomic_fetch_add;
using ::atomic_fetch_add_explicit;
using ::atomic_fetch_and;
using ::atomic_fetch_and_explicit;
using ::atomic_fetch_or;
using ::atomic_fetch_or_explicit;
using ::atomic_fetch_sub;
using ::atomic_fetch_sub_explicit;
using ::atomic_flag_clear;
using ::atomic_flag_clear_explicit;
using ::atomic_flag_test_and_set;
using ::atomic_flag_test_and_set_explicit;
using ::atomic_is_lock_free;
using ::atomic_load;
using ::atomic_load_explicit;
using ::atomic_store;
using ::atomic_store_explicit;
} // namespace test
static_assert(std::atomic_thread_fence == atomic_thread_fence);
static_assert(std::atomic_signal_fence == atomic_signal_fence);
int main() {} // COMPILE-ONLY

Просмотреть файл

@ -1498,6 +1498,20 @@ STATIC_ASSERT(__cpp_lib_starts_ends_with == 201711L);
#endif
#endif
#if _HAS_CXX23
#ifndef __cpp_lib_stdatomic_h
#error __cpp_lib_stdatomic_h is not defined
#elif __cpp_lib_stdatomic_h != 202011L
#error __cpp_lib_stdatomic_h is not 202011L
#else
STATIC_ASSERT(__cpp_lib_stdatomic_h == 202011L);
#endif
#else
#ifdef __cpp_lib_stdatomic_h
#error __cpp_lib_stdatomic_h is defined
#endif
#endif
#if _HAS_CXX23
#ifndef __cpp_lib_string_contains
#error __cpp_lib_string_contains is not defined

Просмотреть файл

@ -64,6 +64,7 @@ PM_CL="/DMEOW_HEADER=source_location"
PM_CL="/DMEOW_HEADER=span"
PM_CL="/DMEOW_HEADER=sstream"
PM_CL="/DMEOW_HEADER=stack"
PM_CL="/DMEOW_HEADER=stdatomic.h"
PM_CL="/DMEOW_HEADER=stdexcept"
PM_CL="/DMEOW_HEADER=stop_token"
PM_CL="/DMEOW_HEADER=streambuf"