Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

atomic_ref (#2, p0019r8) #843

Merged
merged 145 commits into from
Aug 13, 2020
Merged
Show file tree
Hide file tree
Changes from 76 commits
Commits
Show all changes
145 commits
Select commit Hold shift + click to select a range
1cf7cad
atomic_ref (#2, p0019r8)
AlexGuteniev May 17, 2020
001e340
clang format, volatile overload
AlexGuteniev May 17, 2020
75a155d
no really `volatile` overload for atomic_ref
AlexGuteniev May 17, 2020
85ba6a2
no really `volatile` overload for atomic_ref
AlexGuteniev May 17, 2020
9d610cc
required_alignment
AlexGuteniev May 17, 2020
857c620
Don't use _Spinlock
AlexGuteniev May 17, 2020
1ca420a
Do use spinlock
AlexGuteniev May 17, 2020
a522d3b
fix build
AlexGuteniev May 17, 2020
25f603b
direction
AlexGuteniev May 17, 2020
85c044e
Pointer to object for atomic ref mutex init
AlexGuteniev May 17, 2020
2cb4d3e
clang format
AlexGuteniev May 17, 2020
c938bf2
Correct base for specializations
AlexGuteniev May 17, 2020
012bf46
basic operations test
AlexGuteniev May 17, 2020
da247a6
Fix spinlock initialization
AlexGuteniev May 17, 2020
0c38cdc
elaborate test
AlexGuteniev May 17, 2020
3e3cd47
better naming
AlexGuteniev May 17, 2020
6fdcf4d
better naming
AlexGuteniev May 17, 2020
f385fa1
warnings fix
AlexGuteniev May 17, 2020
dac5c6a
get back mutable
AlexGuteniev May 17, 2020
c8d38df
clang format
AlexGuteniev May 17, 2020
3cf38d6
satellite
AlexGuteniev May 17, 2020
dd33205
feature
AlexGuteniev May 17, 2020
fc29559
Use SRWLOCK and abandon _Spinlock for atomic_ref
AlexGuteniev May 17, 2020
e219b71
ref
AlexGuteniev May 17, 2020
9229c12
ARM spinlock
AlexGuteniev May 17, 2020
a266baa
clang format
AlexGuteniev May 17, 2020
2f992db
clang format
AlexGuteniev May 17, 2020
24f1f01
found a way to use spinlock pointer for atomic_ref
AlexGuteniev May 17, 2020
b166dd1
clang format
AlexGuteniev May 17, 2020
e3c2331
missing strong CAS
AlexGuteniev May 17, 2020
b4973b3
Consistently use value type
AlexGuteniev May 17, 2020
15bbdbe
Consistently use value type
AlexGuteniev May 17, 2020
4d07c1c
Remove volatile overloads for atomic_ref
AlexGuteniev May 23, 2020
ef2adde
try to define vNext as well
AlexGuteniev May 23, 2020
3b90ac0
Merge remote-tracking branch 'upstream/master' into atomic_ref
AlexGuteniev May 23, 2020
49b7f95
Zero pad for potential future redefinition
AlexGuteniev May 23, 2020
1be9a85
Warn about misuse
AlexGuteniev May 25, 2020
91f3819
clang-format
AlexGuteniev May 25, 2020
f3e9c76
might
AlexGuteniev May 25, 2020
fe2e25f
formatting
AlexGuteniev May 25, 2020
17297a9
drop static check, keep only runtime
AlexGuteniev May 25, 2020
45191a0
drop static check, keep only runtime
AlexGuteniev May 25, 2020
8f18bbe
fix tests pass
AlexGuteniev May 25, 2020
35388d9
Correct _Init_spinlock_for_ref for current ABI
AlexGuteniev May 25, 2020
0ff9148
constexpr
AlexGuteniev May 25, 2020
549a856
clang format, const, noexcept
AlexGuteniev May 25, 2020
cec012a
whitespace
AlexGuteniev May 25, 2020
f9f876c
fix incorrect test, satisfy required alignment
AlexGuteniev May 26, 2020
fed136c
clang format
AlexGuteniev May 26, 2020
a1a34aa
Merge remote-tracking branch 'upstream/master' into atomic_ref
AlexGuteniev May 30, 2020
f59ed29
fail libcxx test for correct reason
AlexGuteniev Jun 9, 2020
7849930
Merge remote-tracking branch 'upstream/master' into atomic_ref
AlexGuteniev Jun 30, 2020
a7dd4bb
Merge branch 'master' into atomic_ref
AlexGuteniev Jul 8, 2020
bf1af3f
line ending fix after merge via GitHub web face
AlexGuteniev Jul 8, 2020
a4eb73c
Merge remote-tracking branch 'upstream/master' into atomic_ref
AlexGuteniev Jul 9, 2020
5421ee9
Fix merge error
AlexGuteniev Jul 10, 2020
5992ce5
Update stl/inc/atomic
AlexGuteniev Jul 15, 2020
a08ebbf
revive atomic_ref<16 bytes>
AlexGuteniev Jul 17, 2020
db63179
Merge branch 'atomic_ref' of https://github.com/AlexGuteniev/STL into…
AlexGuteniev Jul 17, 2020
5bf9c93
good mutex
AlexGuteniev Jul 17, 2020
8868246
clang format
AlexGuteniev Jul 17, 2020
f35df6b
fix build
AlexGuteniev Jul 17, 2020
64d364e
clang format
AlexGuteniev Jul 17, 2020
2b7bc84
fix build
AlexGuteniev Jul 17, 2020
5829541
implement fallback
AlexGuteniev Jul 17, 2020
68b134f
try to fix tests
AlexGuteniev Jul 17, 2020
c9a3baa
go home clang format you're drunk
AlexGuteniev Jul 17, 2020
94b0990
Merge remote-tracking branch 'upstream/master' into atomic_ref
AlexGuteniev Jul 25, 2020
081890d
merge typo fix
AlexGuteniev Jul 25, 2020
a9130fe
merge: fix _Ty with _TVal in padding bits part
AlexGuteniev Jul 25, 2020
48262ad
Implement padding bits for 16 byte type
AlexGuteniev Jul 25, 2020
547e775
test coverage for 16 byte type
AlexGuteniev Jul 25, 2020
297a97e
Merge remote-tracking branch 'upstream/master' into atomic_ref
AlexGuteniev Aug 1, 2020
8a81301
Merge remote-tracking branch 'upstream/master' into atomic_ref
AlexGuteniev Aug 2, 2020
516a09c
post merge fixes
AlexGuteniev Aug 2, 2020
456ff02
more post merge fixes
AlexGuteniev Aug 2, 2020
0a3b79e
Apply suggestions from code review
AlexGuteniev Aug 2, 2020
74d925b
clang format
AlexGuteniev Aug 2, 2020
6ec6912
typename
AlexGuteniev Aug 2, 2020
a3b1d45
atomic ref wait
AlexGuteniev Aug 3, 2020
7645384
fix cmp 16
AlexGuteniev Aug 3, 2020
e24bc24
better fix cmp 16
AlexGuteniev Aug 3, 2020
4d74aeb
empty change to restart build
AlexGuteniev Aug 3, 2020
abc9673
Don't use _nf for now
AlexGuteniev Aug 3, 2020
fe47a46
copy stuff from <intrin.h>
AlexGuteniev Aug 3, 2020
3ec5506
I don't know how to build on ARM64
AlexGuteniev Aug 3, 2020
a1e3c02
I don't know how to build on ARM64
AlexGuteniev Aug 3, 2020
b477b45
align
AlexGuteniev Aug 3, 2020
5593227
format
AlexGuteniev Aug 3, 2020
4d44049
Billy's review comment
AlexGuteniev Aug 4, 2020
a3b729a
Billy's review comment
AlexGuteniev Aug 4, 2020
9608a3e
arm build
AlexGuteniev Aug 4, 2020
bf59db6
"detection" of cmpxchg16b sililar to woa
AlexGuteniev Aug 4, 2020
8c46780
Ban _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B == 0 when _M_ARM64.
BillyONeal Aug 5, 2020
4abebdb
_Spinlock_guard nitpicks.
BillyONeal Aug 5, 2020
690fd0b
Sort msvcp_atomic_wait.src.
BillyONeal Aug 5, 2020
6666848
Fix _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B enforcement on ARM32.
BillyONeal Aug 5, 2020
67b3fb5
Suppress 4324 and ensure entire structure is zeroed.
BillyONeal Aug 5, 2020
318d9c0
Don't define _STD_COMPARE_EXCHANGE_128 for non 64 bit.
BillyONeal Aug 5, 2020
42ea87f
;
AlexGuteniev Aug 5, 2020
db0b368
Apply suggestions from code review
AlexGuteniev Aug 7, 2020
d6cff23
Apply suggestions from code review
AlexGuteniev Aug 7, 2020
3f0fd34
fix atomic_ref interface
AlexGuteniev Aug 7, 2020
da36cb0
Merge branch 'atomic_ref' of https://github.com/AlexGuteniev/STL into…
AlexGuteniev Aug 7, 2020
3fee7e8
clang format
AlexGuteniev Aug 7, 2020
333e585
+store
AlexGuteniev Aug 7, 2020
cc99367
more @STL comments
AlexGuteniev Aug 7, 2020
c583519
Update stl/src/atomic_wait.cpp
AlexGuteniev Aug 7, 2020
ff8a7b4
grammer
AlexGuteniev Aug 7, 2020
909332c
Merge branch 'atomic_ref' of https://github.com/AlexGuteniev/STL into…
AlexGuteniev Aug 7, 2020
508cfd1
more @STL comments
AlexGuteniev Aug 7, 2020
a9e165a
no reinterpret cast to bool
AlexGuteniev Aug 7, 2020
f925380
this is now superfluous
AlexGuteniev Aug 7, 2020
10c1e9e
_MSC_FULL_VER
AlexGuteniev Aug 8, 2020
69f1d82
Merge remote-tracking branch 'upstream/master' into atomic_ref
AlexGuteniev Aug 10, 2020
2f8e7d3
exclude shared_ptr from atomic_ref test
AlexGuteniev Aug 10, 2020
3c52354
+pad bits
AlexGuteniev Aug 10, 2020
3653311
correctly align atomic_ref
AlexGuteniev Aug 10, 2020
8ef2426
try to fix intrinsic problem
AlexGuteniev Aug 10, 2020
86e887f
cleanup
AlexGuteniev Aug 10, 2020
b09b8cc
skip _TVal for facade types
AlexGuteniev Aug 10, 2020
600e5ab
consistent cast syntax
AlexGuteniev Aug 10, 2020
05f1f84
correct is_lock_free
AlexGuteniev Aug 10, 2020
73c026a
correct is_lock_free
AlexGuteniev Aug 10, 2020
52700e2
correct is_lock_free
AlexGuteniev Aug 10, 2020
2aab7ba
clang format
AlexGuteniev Aug 10, 2020
69fc773
build fix
AlexGuteniev Aug 10, 2020
1370b5d
reduce transition
AlexGuteniev Aug 10, 2020
0f9978c
Who said it must be CRITICAL_SECTION?
AlexGuteniev Aug 10, 2020
3702d7b
ARM64
AlexGuteniev Aug 10, 2020
8ae82a5
Windows
AlexGuteniev Aug 10, 2020
ca9b076
_STL
AlexGuteniev Aug 10, 2020
2e8638d
clang format
AlexGuteniev Aug 10, 2020
19f596d
space
AlexGuteniev Aug 10, 2020
fc26176
missing space
AlexGuteniev Aug 11, 2020
be20faa
actually no _TVal here already
AlexGuteniev Aug 11, 2020
e6e9ba0
Update stl/inc/yvals_core.h
AlexGuteniev Aug 12, 2020
0def107
STL comments
AlexGuteniev Aug 12, 2020
18d9e8e
nonstatic constexpr
AlexGuteniev Aug 12, 2020
c0d809b
never a reference here
AlexGuteniev Aug 12, 2020
6ccb054
clang format
AlexGuteniev Aug 12, 2020
d3dcda4
fix atomic ref<16 bytes>
AlexGuteniev Aug 12, 2020
ac2ebe7
clang format
AlexGuteniev Aug 12, 2020
60bc35e
update TRANSITION comment
AlexGuteniev Aug 12, 2020
a270733
Merge remote-tracking branch 'upstream/master' into atomic_ref
AlexGuteniev Aug 12, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions stl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ set(SOURCES_SATELLITE_2
)

set(SOURCES_SATELLITE_ATOMIC_WAIT
${CMAKE_CURRENT_LIST_DIR}/src/atomic_ref.cpp
${CMAKE_CURRENT_LIST_DIR}/src/atomic_wait.cpp
${CMAKE_CURRENT_LIST_DIR}/src/parallel_algorithms.cpp
)
Expand Down
809 changes: 523 additions & 286 deletions stl/inc/atomic

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions stl/inc/yvals.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,21 @@ _STL_DISABLE_CLANG_WARNINGS
#define _STL_INTERNAL_STATIC_ASSERT(...)
#endif // _ENABLE_STL_INTERNAL_CHECK

#ifndef _ENABLE_ATOMIC_REF_ALIGNMENT_CHECK
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have a use case for this being different than _DEBUG ? OK to leave as is, just curious.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pinpoint tearing in release, that never happens in debug due to timings and debug allocations

#ifdef _DEBUG
#define _ENABLE_ATOMIC_REF_ALIGNMENT_CHECK 1
#else // ^^^ _DEBUG ^^^ // vvv !_DEBUG vvv
#define _ENABLE_ATOMIC_REF_ALIGNMENT_CHECK 0
#endif // _DEBUG
#endif // _ENABLE_ATOMIC_REF_ALIGNMENT_CHECK

#if _ENABLE_ATOMIC_REF_ALIGNMENT_CHECK
#define _ATOMIC_REF_CHECK_ALIGNMENT(cond, mesg) _STL_VERIFY(cond, mesg)
#else
#define _ATOMIC_REF_CHECK_ALIGNMENT(cond, mesg) _Analysis_assume_(cond)
#endif


#include <use_ansi.h>

#define _WARNING_MESSAGE(NUMBER, MESSAGE) __FILE__ "(" _CRT_STRINGIZE(__LINE__) "): warning " NUMBER ": " MESSAGE
Expand Down
1 change: 1 addition & 0 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -1137,6 +1137,7 @@
#define __cpp_lib_atomic_flag_test 201907L
#define __cpp_lib_atomic_float 201711L
#define __cpp_lib_atomic_lock_free_type_aliases 201907L
#define __cpp_lib_atomic_ref 201806L
AlexGuteniev marked this conversation as resolved.
Show resolved Hide resolved
#define __cpp_lib_atomic_shared_ptr 201711L
#define __cpp_lib_atomic_wait 201907L
#define __cpp_lib_bind_front 201907L
Expand Down
100 changes: 100 additions & 0 deletions stl/src/atomic_ref.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

// implement atomic_ref spin lock

#include <atomic>
#include <cstdint>
#include <intrin.h>
#include <new>
#include <synchapi.h>
#include <xthreads.h>

_EXTERN_C
_Smtx_t* __stdcall __std_atomic_get_mutex(const void* const _Key) noexcept {
constexpr size_t _Table_size_power = 8;
constexpr size_t _Table_size = 1 << _Table_size_power;
constexpr size_t _Table_index_mask = _Table_size - 1;

struct alignas(std::hardware_destructive_interference_size) _Table_entry {
_Smtx_t _Mutex = 0;
char _Pad[std::hardware_destructive_interference_size - sizeof(_Smtx_t)] = {};
};
static _Table_entry _Table[_Table_size];
AlexGuteniev marked this conversation as resolved.
Show resolved Hide resolved

auto _Index = reinterpret_cast<const std::uintptr_t>(_Key);
_Index ^= _Index >> (_Table_size_power * 2);
_Index ^= _Index >> _Table_size_power;
return &_Table[_Index & _Table_index_mask]._Mutex;
}

namespace {

_NODISCARD unsigned char __std_atomic_compare_exchange_128_fallback(_Inout_bytecount_(16) long long* _Destination,
_In_ long long _ExchangeHigh, _In_ long long _ExchangeLow,
_Inout_bytecount_(16) long long* _ComparandResult) noexcept {
static SRWLOCK _Mtx = SRWLOCK_INIT;
AcquireSRWLockExclusive(&_Mtx);
AlexGuteniev marked this conversation as resolved.
Show resolved Hide resolved
if (_Destination[0] == _ComparandResult[0] && _Destination[1] == _ComparandResult[1]) {
_ComparandResult[0] = _Destination[0];
_ComparandResult[1] = _Destination[1];
_Destination[0] = _ExchangeLow;
_Destination[1] = _ExchangeHigh;
ReleaseSRWLockExclusive(&_Mtx);
return true;
} else {
_ComparandResult[0] = _Destination[0];
_ComparandResult[1] = _Destination[1];
ReleaseSRWLockExclusive(&_Mtx);
return false;
}
}

} // unnamed namespace

_NODISCARD unsigned char __stdcall __std_atomic_compare_exchange_128(_Inout_bytecount_(16) long long* _Destination,
_In_ long long _ExchangeHigh, _In_ long long _ExchangeLow,
_Inout_bytecount_(16) long long* _ComparandResult) noexcept {
#if defined(_M_X64)
if (__std_atomic_has_cmpxchg16b()) {
return _InterlockedCompareExchange128(_Destination, _ExchangeHigh, _ExchangeLow, _ComparandResult);
} else {
return __std_atomic_compare_exchange_128_fallback(_Destination, _ExchangeHigh, _ExchangeLow, _ComparandResult);
}
#elif defined(_M_ARM64)
return _InterlockedCompareExchange128(_Destination, _ExchangeHigh, _ExchangeLow, _ComparandResult);
#else
return __std_atomic_compare_exchange_128_fallback(_Destination, _ExchangeHigh, _ExchangeLow, _ComparandResult);
#endif
}

_NODISCARD bool __stdcall __std_atomic_has_cmpxchg16b() noexcept {
#if defined(_M_X64)
enum class _Cmpxchg16_support : char {
_Absent = false,
_Present = true,
_Unknown,
};
static std::atomic<_Cmpxchg16_support> _Cached_value{_Cmpxchg16_support::_Unknown};

_Cmpxchg16_support _Value = _Cached_value.load(std::memory_order_relaxed);

if (_Value == _Cmpxchg16_support::_Unknown) {
int regs[4];
__cpuid(regs, 1); // assume leaf 1 exists
AlexGuteniev marked this conversation as resolved.
Show resolved Hide resolved
if (regs[2] & (1 << 13)) {
_Value = _Cmpxchg16_support::_Present;
} else {
_Value = _Cmpxchg16_support::_Absent;
}
_Cached_value.store(_Value, std::memory_order_relaxed);
}
return reinterpret_cast<bool&>(_Value);
#elif defined(_M_ARM64)
return true;
#else
return false;
#endif
}

_END_EXTERN_C
3 changes: 3 additions & 0 deletions stl/src/msvcp_atomic_wait.src
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
LIBRARY LIBRARYNAME

EXPORTS
__std_atomic_compare_exchange_128
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BillyONeal Is there a list of exports that we need to update for the "have the exports changed" build-time test? (I think that might still be MSVC-internal.) Are we running such a check against the atomic_wait satellite yet?

__std_atomic_has_cmpxchg16b
__std_atomic_get_mutex
__std_atomic_wait_get_deadline
__std_atomic_wait_get_remaining_timeout
__std_atomic_notify_all_direct
Expand Down
4 changes: 1 addition & 3 deletions tests/libcxx/expected_results.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ std/containers/unord/unord.map/unord.map.modifiers/insert_and_emplace_allocator_
std/containers/unord/unord.set/insert_and_emplace_allocator_requirements.pass.cpp FAIL

# libc++ doesn't yet implement P1423R3, so it expects an old value for `__cpp_lib_char8_t`
std/language.support/support.limits/support.limits.general/atomic.version.pass.cpp FAIL
std/language.support/support.limits/support.limits.general/filesystem.version.pass.cpp FAIL
std/language.support/support.limits/support.limits.general/istream.version.pass.cpp FAIL
std/language.support/support.limits/support.limits.general/limits.version.pass.cpp FAIL
Expand Down Expand Up @@ -252,9 +253,6 @@ std/utilities/memory/default.allocator/allocator.members/allocate.verify.cpp SKI


# *** MISSING STL FEATURES ***
# C++20 P0019R8 "atomic_ref"
std/language.support/support.limits/support.limits.general/atomic.version.pass.cpp FAIL

# C++20 P0355R7 "<chrono> Calendars And Time Zones"
std/utilities/time/days.pass.cpp FAIL
std/utilities/time/months.pass.cpp FAIL
Expand Down
4 changes: 1 addition & 3 deletions tests/libcxx/skipped_tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ containers\unord\unord.map\unord.map.modifiers\insert_and_emplace_allocator_requ
containers\unord\unord.set\insert_and_emplace_allocator_requirements.pass.cpp

# libc++ doesn't yet implement P1423R3, so it expects an old value for `__cpp_lib_char8_t`
language.support\support.limits\support.limits.general\atomic.version.pass.cpp
language.support\support.limits\support.limits.general\filesystem.version.pass.cpp
language.support\support.limits\support.limits.general\istream.version.pass.cpp
language.support\support.limits\support.limits.general\limits.version.pass.cpp
Expand Down Expand Up @@ -252,9 +253,6 @@ utilities\memory\default.allocator\allocator.members\allocate.verify.cpp


# *** MISSING STL FEATURES ***
# C++20 P0019R8 "atomic_ref"
language.support\support.limits\support.limits.general\atomic.version.pass.cpp

# C++20 P0355R7 "<chrono> Calendars And Time Zones"
utilities\time\days.pass.cpp
utilities\time\months.pass.cpp
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ tests\GH_001010_filesystem_error_encoding
tests\GH_001017_discrete_distribution_out_of_range
tests\LWG2597_complex_branch_cut
tests\LWG3018_shared_ptr_function
tests\P0019R8_atomic_ref
tests\P0024R2_parallel_algorithms_adjacent_difference
tests\P0024R2_parallel_algorithms_adjacent_find
tests\P0024R2_parallel_algorithms_all_of
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P0019R8_atomic_ref/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_latest_matrix.lst
120 changes: 120 additions & 0 deletions tests/std/tests/P0019R8_atomic_ref/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <atomic>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <execution>
#include <vector>

struct bigint {
int value;
int more_value[10];

bigint(int value = 0) : value(value) {}
AlexGuteniev marked this conversation as resolved.
Show resolved Hide resolved

operator int() const {
return value;
}
};

struct int128 {
long long value;
long long more_value;

int128(int value = 0) : value(value), more_value(0) {}

operator int() const {
return static_cast<int>(value);
}
};


// code reuse of ../P1135R6_atomic_flag_test/test.cpp

template <bool AddViaCas, typename ValueType>
void test_ops() {
constexpr std::size_t unique = 80; // small to avoid overflow even for char
constexpr std::size_t repetitions = 8000;
constexpr std::size_t total = unique * repetitions;
constexpr std::size_t range = 10;

struct alignas(std::atomic_ref<ValueType>::required_alignment) Padded {
ValueType vals[unique] = {};
} padded;

auto& vals = padded.vals;

std::vector<std::atomic_ref<ValueType>> refs;
refs.reserve(total);
for (std::size_t i = 0; i != repetitions; ++i) {
for (auto& val : vals) {
refs.push_back(std::atomic_ref<ValueType>(val));
AlexGuteniev marked this conversation as resolved.
Show resolved Hide resolved
}
}

using std::execution::par;

auto load = [](const std::atomic_ref<ValueType>& ref) { return static_cast<int>(ref.load()); };
auto xchg0 = [](std::atomic_ref<ValueType>& ref) { return static_cast<int>(ref.exchange(0)); };

int (*inc)(std::atomic_ref<ValueType> & ref);
if constexpr (AddViaCas) {
inc = [](std::atomic_ref<ValueType>& ref) {
for (;;) {
ValueType e = ref.load();
ValueType d = static_cast<ValueType>(static_cast<int>(e) + 1);
if (ref.compare_exchange_weak(e, d)) {
return static_cast<int>(e);
}
}
};
} else {
inc = [](std::atomic_ref<ValueType>& ref) { return static_cast<int>(ref.fetch_add(1)); };
}

assert(std::transform_reduce(par, refs.begin(), refs.end(), 0, std::plus{}, load) == 0);
AlexGuteniev marked this conversation as resolved.
Show resolved Hide resolved
assert(std::transform_reduce(par, refs.begin(), refs.begin() + range, 0, std::plus{}, inc) == 0);
assert(std::transform_reduce(par, refs.begin(), refs.end(), 0, std::plus{}, load) == range * repetitions);
assert(std::transform_reduce(par, refs.begin(), refs.begin() + range, 0, std::plus{}, inc) == range);
assert(std::transform_reduce(par, refs.begin(), refs.end(), 0, std::plus{}, load) == range * repetitions * 2);
assert(std::transform_reduce(par, refs.begin(), refs.end(), 0, std::plus{}, xchg0) == range * 2);
assert(std::transform_reduce(par, refs.begin(), refs.end(), 0, std::plus{}, load) == 0);
}

#include <intrin.h>
AlexGuteniev marked this conversation as resolved.
Show resolved Hide resolved

int main() {
AlexGuteniev marked this conversation as resolved.
Show resolved Hide resolved
test_ops<false, char>();
test_ops<false, signed char>();
test_ops<false, unsigned char>();
test_ops<false, short>();
test_ops<false, unsigned short>();
test_ops<false, int>();
test_ops<false, unsigned int>();
test_ops<false, long>();
test_ops<false, unsigned long>();
test_ops<false, long long>();
test_ops<false, unsigned long long>();
test_ops<false, float>();
test_ops<false, double>();
test_ops<false, long double>();

test_ops<true, char>();
test_ops<true, signed char>();
test_ops<true, unsigned char>();
test_ops<true, short>();
test_ops<true, unsigned short>();
test_ops<true, int>();
test_ops<true, unsigned int>();
test_ops<true, long>();
test_ops<true, unsigned long>();
test_ops<true, long long>();
test_ops<true, unsigned long long>();
test_ops<true, float>();
test_ops<true, double>();
test_ops<true, long double>();
test_ops<true, bigint>();
test_ops<true, int128>();
}
Loading