Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
4fddd84
Extract simple part from #593 to have it earlier
AlexGuteniev Apr 3, 2020
d517d28
missing _NODISCARD
AlexGuteniev Apr 3, 2020
b79074f
Merge remote-tracking branch 'upstream/master' into atomic_flag_test
AlexGuteniev Apr 7, 2020
3ae2c0a
Add test
AlexGuteniev Apr 10, 2020
d0eae56
Merge remote-tracking branch 'upstream/master' into atomic_flag_test
AlexGuteniev Apr 10, 2020
f2e5be5
a bit more smoke tests
AlexGuteniev Apr 10, 2020
a783c22
fix incorrect merge
AlexGuteniev Apr 10, 2020
f9f6d9d
Merge remote-tracking branch 'upstream/master' into atomic_flag_test
AlexGuteniev Apr 23, 2020
ec1fcad
Update tests/tr1/tests/atomic/test.cpp
AlexGuteniev Apr 25, 2020
35e5ca3
Update tests/tr1/tests/atomic/test.cpp
AlexGuteniev Apr 25, 2020
775eb0d
Revert "Add test"
AlexGuteniev Apr 25, 2020
4d082b8
Merge branch 'atomic_flag_test' of https://github.com/AlexGuteniev/ST…
AlexGuteniev Apr 25, 2020
b912697
better test for atomic flags
AlexGuteniev Apr 25, 2020
1a4e2be
newline
AlexGuteniev Apr 25, 2020
e469137
actually relaxed is wrong
AlexGuteniev Apr 25, 2020
314a05d
don't capture mo
AlexGuteniev Apr 26, 2020
d16e111
Merge remote-tracking branch 'upstream/master' into atomic_flag_test
AlexGuteniev May 1, 2020
53c7236
Merge remote-tracking branch 'upstream/master' into atomic_flag_test
AlexGuteniev May 7, 2020
4306cdb
I expect it to pass
AlexGuteniev May 7, 2020
1e79f53
Merge branch 'master' into atomic_flag_test
StephanTLavavej May 9, 2020
66b6275
Code review feedback.
StephanTLavavej May 9, 2020
949b259
Code review feedback, part 2.
StephanTLavavej May 9, 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
35 changes: 35 additions & 0 deletions stl/inc/atomic
Original file line number Diff line number Diff line change
Expand Up @@ -2018,11 +2018,27 @@ using atomic_ptrdiff_t = atomic<ptrdiff_t>;
using atomic_intmax_t = atomic<intmax_t>;
using atomic_uintmax_t = atomic<uintmax_t>;

#if _HAS_CXX20
// Though there are CMPXCHG8B and CMPXCHG16B,
// the largest atomics with a full set of efficient operations are pointer-sized.
using atomic_signed_lock_free = atomic_intptr_t;
using atomic_unsigned_lock_free = atomic_uintptr_t;
#endif // _HAS_CXX20

// STRUCT atomic_flag
#define ATOMIC_FLAG_INIT \
{}
struct atomic_flag { // flag with test-and-set semantics
#if _HAS_CXX20
_NODISCARD bool test(const memory_order _Order = memory_order_seq_cst) const noexcept {
return _Storage.load(_Order) != 0;
}

_NODISCARD bool test(const memory_order _Order = memory_order_seq_cst) const volatile noexcept {
return _Storage.load(_Order) != 0;
}
#endif // _HAS_CXX20

bool test_and_set(const memory_order _Order = memory_order_seq_cst) noexcept {
return _Storage.exchange(true, _Order) != 0;
}
Expand Down Expand Up @@ -2050,6 +2066,25 @@ struct atomic_flag { // flag with test-and-set semantics


// atomic_flag NONMEMBERS
#if _HAS_CXX20
_NODISCARD inline bool atomic_flag_test(const volatile atomic_flag* const _Flag) noexcept {
return _Flag->test();
}

_NODISCARD inline bool atomic_flag_test(const atomic_flag* const _Flag) noexcept {
return _Flag->test();
}

_NODISCARD inline bool atomic_flag_test_explicit(
const volatile atomic_flag* const _Flag, const memory_order _Order) noexcept {
return _Flag->test(_Order);
}

_NODISCARD inline bool atomic_flag_test_explicit(const atomic_flag* const _Flag, const memory_order _Order) noexcept {
return _Flag->test(_Order);
}
#endif // _HAS_CXX20

inline bool atomic_flag_test_and_set(atomic_flag* _Flag) noexcept {
return _Flag->test_and_set();
}
Expand Down
10 changes: 6 additions & 4 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -1130,10 +1130,12 @@
#define __cpp_lib_atomic_value_initialization 201911L

#if _HAS_CXX20
#define __cpp_lib_atomic_float 201711L
#define __cpp_lib_atomic_shared_ptr 201711L
#define __cpp_lib_bind_front 201907L
#define __cpp_lib_bit_cast 201806L
#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_shared_ptr 201711L
#define __cpp_lib_bind_front 201907L
#define __cpp_lib_bit_cast 201806L

#ifdef __clang__ // TRANSITION, VSO-1020212
// a future MSVC update will embed CPU feature detection into <bit> intrinsics
Expand Down
1 change: 0 additions & 1 deletion tests/libcxx/expected_results.txt
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,6 @@ std/strings/char.traits/char.traits.specializations/char.traits.specializations.
std/strings/char.traits/char.traits.specializations/char.traits.specializations.wchar.t/move.pass.cpp FAIL

# C++20 P1135R6 "The C++20 Synchronization Library"
std/atomics/types.pass.cpp FAIL
std/atomics/atomics.types.operations/atomics.types.operations.wait/atomic_wait.pass.cpp FAIL
std/thread/thread.barrier/arrive.pass.cpp FAIL
std/thread/thread.barrier/arrive_and_drop.pass.cpp FAIL
Expand Down
1 change: 0 additions & 1 deletion tests/libcxx/skipped_tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,6 @@ strings\char.traits\char.traits.specializations\char.traits.specializations.wcha
strings\char.traits\char.traits.specializations\char.traits.specializations.wchar.t\move.pass.cpp

# C++20 P1135R6 "The C++20 Synchronization Library"
atomics\types.pass.cpp
atomics\atomics.types.operations\atomics.types.operations.wait\atomic_wait.pass.cpp
thread\thread.barrier\arrive.pass.cpp
thread\thread.barrier\arrive_and_drop.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 @@ -254,6 +254,7 @@ tests\P0898R3_identity
tests\P0919R3_heterogeneous_unordered_lookup
tests\P0966R1_string_reserve_should_not_shrink
tests\P1023R0_constexpr_for_array_comparisons
tests\P1135R6_atomic_flag_test
tests\P1165R1_consistently_propagating_stateful_allocators
tests\P1423R3_char8_t_remediation
tests\P1645R1_constexpr_numeric
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P1135R6_atomic_flag_test/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
87 changes: 87 additions & 0 deletions tests/std/tests/P1135R6_atomic_flag_test/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <algorithm>
#include <atomic>
#include <cassert>
#include <cstddef>
#include <execution>
#include <numeric>
#include <vector>

constexpr auto mo = std::memory_order_seq_cst;

template <typename FlagType, typename IsSet, typename TestAndSet, typename Clear>
void test_flags(const IsSet is_set, const TestAndSet test_and_set, const Clear clear) {
constexpr std::size_t unique = 800;
constexpr std::size_t repetitions = 800;
constexpr std::size_t total = unique * repetitions;
constexpr std::size_t dups = total - unique;

FlagType flags[unique];
std::vector<FlagType*> ptrs;
ptrs.reserve(total);
for (std::size_t i = 0; i != repetitions; ++i) {
for (auto& flag : flags) {
ptrs.push_back(&flag);
}
}

using std::execution::par;

assert(std::transform_reduce(par, ptrs.begin(), ptrs.end(), 0, std::plus{}, is_set) == 0);
assert(std::transform_reduce(par, ptrs.begin(), ptrs.end(), 0, std::plus{}, test_and_set) == dups);
assert(std::transform_reduce(par, ptrs.begin(), ptrs.end(), 0, std::plus{}, is_set) == total);
assert(std::transform_reduce(par, ptrs.begin(), ptrs.end(), 0, std::plus{}, test_and_set) == total);
std::for_each(par, ptrs.begin(), ptrs.end(), clear);
assert(std::transform_reduce(par, ptrs.begin(), ptrs.end(), 0, std::plus{}, is_set) == 0);
}

template <typename FlagType>
void test_flags_members() {
const auto is_set = [](const FlagType* f) { return f->test(); };
const auto test_and_set = [](FlagType* f) { return f->test_and_set(); };
const auto clear = [](FlagType* f) { f->clear(); };

test_flags<FlagType>(is_set, test_and_set, clear);
}

template <typename FlagType>
void test_flags_members_mo() {
const auto is_set = [](const FlagType* f) { return f->test(mo); };
const auto test_and_set = [](FlagType* f) { return f->test_and_set(mo); };
const auto clear = [](FlagType* f) { f->clear(mo); };

test_flags<FlagType>(is_set, test_and_set, clear);
}

template <typename FlagType>
void test_flags_free() {
const auto is_set = [](const FlagType* f) { return std::atomic_flag_test(f); };
const auto test_and_set = [](FlagType* f) { return std::atomic_flag_test_and_set(f); };
const auto clear = [](FlagType* f) { std::atomic_flag_clear(f); };

test_flags<FlagType>(is_set, test_and_set, clear);
}

template <typename FlagType>
void test_flags_free_mo() {
const auto is_set = [](const FlagType* f) { return std::atomic_flag_test_explicit(f, mo); };
const auto test_and_set = [](FlagType* f) { return std::atomic_flag_test_and_set_explicit(f, mo); };
const auto clear = [](FlagType* f) { std::atomic_flag_clear_explicit(f, mo); };

test_flags<FlagType>(is_set, test_and_set, clear);
}

template <typename FlagType>
void test_flag_type() {
test_flags_members<FlagType>();
test_flags_free<FlagType>();
test_flags_members_mo<FlagType>();
test_flags_free_mo<FlagType>();
}

int main() {
test_flag_type<std::atomic_flag>();
test_flag_type<volatile std::atomic_flag>();
}
28 changes: 28 additions & 0 deletions tests/std/tests/VSO_0157762_feature_test_macros/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,20 @@ STATIC_ASSERT(__cpp_lib_array_constexpr == 201803L);
STATIC_ASSERT(__cpp_lib_as_const == 201510L);
#endif

#if _HAS_CXX20
#ifndef __cpp_lib_atomic_flag_test
#error __cpp_lib_atomic_flag_test is not defined
#elif __cpp_lib_atomic_flag_test != 201907L
#error __cpp_lib_atomic_flag_test is not 201907L
#else
STATIC_ASSERT(__cpp_lib_atomic_flag_test == 201907L);
#endif
#else
#ifdef __cpp_lib_atomic_flag_test
#error __cpp_lib_atomic_flag_test is defined
#endif
#endif

#if _HAS_CXX20
#ifndef __cpp_lib_atomic_float
#error __cpp_lib_atomic_float is not defined
Expand Down Expand Up @@ -111,6 +125,20 @@ STATIC_ASSERT(__cpp_lib_atomic_is_always_lock_free == 201603L);
#endif
#endif

#if _HAS_CXX20
#ifndef __cpp_lib_atomic_lock_free_type_aliases
#error __cpp_lib_atomic_lock_free_type_aliases is not defined
#elif __cpp_lib_atomic_lock_free_type_aliases != 201907L
#error __cpp_lib_atomic_lock_free_type_aliases is not 201907L
#else
STATIC_ASSERT(__cpp_lib_atomic_lock_free_type_aliases == 201907L);
#endif
#else
#ifdef __cpp_lib_atomic_lock_free_type_aliases
#error __cpp_lib_atomic_lock_free_type_aliases is defined
#endif
#endif

#if _HAS_CXX20
#ifndef __cpp_lib_atomic_shared_ptr
#error __cpp_lib_atomic_shared_ptr is not defined
Expand Down