-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Latch, Semaphore, Barrier (part of #52, P1135R6) #1057
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
Merged
Merged
Changes from all commits
Commits
Show all changes
470 commits
Select commit
Hold shift + click to select a range
be86c90
Formatting
AlexGuteniev 57f15ca
ARM build
AlexGuteniev ca11289
Merge remote-tracking branch 'upstream/master'
AlexGuteniev cbb2803
I expect it to pass
AlexGuteniev f2f01a1
Don't try to support nonexistent "old ABI"
AlexGuteniev 7b4a03a
formatting
AlexGuteniev 9acff2e
Update stl/inc/xatomic_wait.h
AlexGuteniev 7069749
Update stl/inc/xatomic_wait.h
AlexGuteniev 380c281
Update stl/inc/memory
AlexGuteniev 073f30b
Update stl/inc/atomic
AlexGuteniev 9c5cb7e
correctly mark test as passing
AlexGuteniev e9969c1
duplicate duplicate
AlexGuteniev 237f535
Merge branch 'master' of https://github.com/AlexGuteniev/STL
AlexGuteniev 750356b
abort on unexpected situation even in release
AlexGuteniev 0f89af1
actually don't see a value in this check
AlexGuteniev 84d32f0
too much mimic of existing code by too much copying
AlexGuteniev 2dbcf8e
Merge remote-tracking branch 'upstream/master'
AlexGuteniev 53f056f
Merge remote-tracking branch 'upstream/master'
AlexGuteniev edff7ca
More time to pass test
AlexGuteniev f8f9abe
Merge remote-tracking branch 'upstream/master'
AlexGuteniev 9ca6c15
Merge remote-tracking branch 'upstream/master'
AlexGuteniev 4287866
Merge remote-tracking branch 'origin/master' into HEAD
BillyONeal f34dee5
Merge remote-tracking branch 'origin/master' into atomic_wait
BillyONeal 05a65fa
Add msbuild build system.
BillyONeal e46c447
Manually inline _Save_function_pointer_relaxed -- I think atomic ops …
BillyONeal 7f05ee2
More build fixes discovered in DevDiv test harness
BillyONeal 4dcd154
Merge remote-tracking branch 'origin/master' into atomic_wait
BillyONeal 9dcb98e
clang-format
BillyONeal 83290f4
Fix cmake dependency information for the .src, thanks to Robert Schum…
BillyONeal f8e6cea
_Ugly some things in atomic_wait.cpp
BillyONeal 4c454e7
Merge _Atomic_wait_direct_timed_for_internal_spinlock into only caller.
BillyONeal 6e3951d
de-inline template
BillyONeal e80bbc6
Remove synchronization.lib pragma which is problematic for _ONECORE p…
BillyONeal bb15189
Rename _Deadline_picoseconds to _Reserved as it is currently unused.
BillyONeal 84df7ef
Rename _Get_remaining_waiting_time to _Get_remaining_wait_millisecond…
BillyONeal 653c270
Merge remote-tracking branch 'origin/master' into atomic_wait
BillyONeal f866822
fixup
BillyONeal e8b38a1
Add missing _INLINE_VAR.
BillyONeal c8f10c6
Merge remote-tracking branch 'upstream/master'
AlexGuteniev f3ffdaf
Merge remote-tracking branch 'origin/master'
AlexGuteniev 8fa9d54
Update stl/inc/atomic
AlexGuteniev 21b0352
Update stl/inc/memory
AlexGuteniev c3aa7e1
Fix CMakeLists.txt declaration order.
BillyONeal eb99cd0
Fix test sort order.
BillyONeal 0b0de84
Use <assert.h> and pragma once.
BillyONeal 74ab22a
STL CR feedback:
BillyONeal aaf8f46
Merge remote-tracking branch 'AlexGuteniev/master' into atomic_wait
BillyONeal 0334bda
Compiler errors.
BillyONeal c281047
Fix the same build system bug in the cmake version.
BillyONeal 7565517
Find missing ^^^s with regex:
BillyONeal bdeb5ad
Bill forgot to save before committing.
BillyONeal dcf4216
remove spinner to pass tests
AlexGuteniev 1caf417
Correct default for wait phase
AlexGuteniev 71d5d1b
whitespace
AlexGuteniev 54c2eda
rewrite to avoid the complexity of indirect wait
AlexGuteniev ba3d8c8
clang format
AlexGuteniev c1157f7
notify_one for indirect wake
AlexGuteniev 7327523
clang format
AlexGuteniev fed4f21
optimize acquire wait functions
AlexGuteniev 2c348af
latch, part of #52, based on atomic wait
AlexGuteniev cf43fdc
formatting
AlexGuteniev 26ac662
consistency
AlexGuteniev e0c4a08
another const
AlexGuteniev e777a8b
p1865r1
AlexGuteniev 97c72c2
unterse
AlexGuteniev 375db7c
typo
AlexGuteniev 209cdfb
avoid dependency on system_error
AlexGuteniev 19a1dd2
feature
AlexGuteniev 902ad61
latch not /clr:pure
AlexGuteniev 50ac866
tests
AlexGuteniev eaed150
c++20 guard
AlexGuteniev 8aab61e
Merge remote-tracking branch 'upstream/master'
AlexGuteniev f5d945e
remove unwait
AlexGuteniev 21a395c
All. Sorry we don't track waiter count.
AlexGuteniev 94f2f87
actually one, we don't track the waiting too
AlexGuteniev 6d78db0
no wheel invention actually
AlexGuteniev b893242
}
AlexGuteniev b627266
whitespace
AlexGuteniev 3e82ec5
actually lets call it "unrecoverable"
AlexGuteniev cebacd5
Merge remote-tracking branch 'upstream/master'
AlexGuteniev c5cb0b9
apply padding bits resolution
AlexGuteniev 18e5184
attempt on 16 bytes case
AlexGuteniev 6726c5d
attempt on 16 bytes case
AlexGuteniev 1b4be08
clang format
AlexGuteniev 866966c
Merge remote-tracking branch 'origin/master' into latch
AlexGuteniev b42025f
attempt on 16 bytes case
AlexGuteniev fe33a36
attempt on 16 bytes case
AlexGuteniev 73c5cc6
Add test for discovered notify_all_indirect deadlock.
BillyONeal 1244e9c
Fix deadlock in notify_all.
BillyONeal c55368f
Add RAII guards.
BillyONeal b308261
Remove timed variants from header; timed infrastructure on the other …
BillyONeal c326f7f
Use return instead of break in the indirect mode.
BillyONeal 66a2e6e
Add comments explaining the ABI layer to <xatomic_wait.h> and remove …
BillyONeal 7edc9f6
Merge pull request #5 from BillyONeal/atomic_upstream
AlexGuteniev 6279b7b
Document deliberately waking before SRWLOCK exit
AlexGuteniev de50735
Direct wait to API convention for aliasobj
AlexGuteniev ba5364d
Some respect to padding bits
AlexGuteniev b9acf63
clang format
AlexGuteniev 3be75d0
Avoid killing correct pad bits of observed value
AlexGuteniev 3ac6b7b
Minor improvements
AlexGuteniev 50b6861
clang format
AlexGuteniev 4d764eb
no loop needed here, caller handles spurious wakes
AlexGuteniev 9a8de74
STL CR comments.
BillyONeal 1703d44
header safety
AlexGuteniev 74f4758
Merge branch 'master' into latch
AlexGuteniev 5fa1b64
+semaphore
AlexGuteniev 1c61535
memory order
AlexGuteniev 44abe1d
correct use of atomic wait
AlexGuteniev 92c2862
+binary_semahpore
AlexGuteniev bbd7ea2
until
AlexGuteniev 73ec64c
max for latch to avoid <limits>
AlexGuteniev 0f5bd2a
update test skip list
AlexGuteniev c9a5b78
handle partial timeout properly
AlexGuteniev 3c4c736
barrier feature stub
AlexGuteniev dbe9bcb
barrier tentative implementation
AlexGuteniev 15cb748
clang-format
AlexGuteniev 50be0b1
fix bae type
AlexGuteniev fa7ae3f
fix, make test pass
AlexGuteniev dc222a9
functor test
AlexGuteniev 4ac114d
fix barrier test, add nodiscard
AlexGuteniev 2f05501
test for max
AlexGuteniev 8faba66
typo
AlexGuteniev bc0f30d
partial timeout one more fix
AlexGuteniev b94e722
clang format
AlexGuteniev 9ec059d
simpler barrier counting
AlexGuteniev f22c43d
calculate step
AlexGuteniev 7628df6
more timeout to avoid spurious fail
AlexGuteniev 2de9335
newline
AlexGuteniev 5241b82
barrier is barrier
AlexGuteniev dabd97a
acquire fence instead of acq_rel,
AlexGuteniev 44c141f
missing weaker order
AlexGuteniev cd9e105
longer rel time
AlexGuteniev 558bda0
actually here it should be acq_rel memory order
AlexGuteniev 770bae9
More reliable arrival_token validation
AlexGuteniev 864772e
fix compile
AlexGuteniev 0f2f42b
()
AlexGuteniev 3af10a4
explicit type would be cleaner than nullptr_t
AlexGuteniev c6cf987
employ empty base optimization for any case
AlexGuteniev d849add
nothrow
AlexGuteniev 735e3e6
get back member
AlexGuteniev 159020b
no_[[no_unique_address]]
AlexGuteniev 940f949
Better empty base optimization selection
AlexGuteniev 39dcae8
Actually cannot report error as exceptions
AlexGuteniev d7ddcbc
Actually cannot report error as exceptions++
AlexGuteniev 95b9630
_STL_VERIFY
AlexGuteniev 1adc379
clang format
AlexGuteniev f0650f1
should notify all
AlexGuteniev a5b42a7
missing return
AlexGuteniev 7abbc71
empty completion to match Standard
AlexGuteniev bc6b6d0
Don't miss empty base
AlexGuteniev 21a0776
Improve _STL_VERIFY
AlexGuteniev 8918b8c
acq+rel for arrive_and_wait
AlexGuteniev 061ccf2
_Ugly
AlexGuteniev b0027e7
fix race
AlexGuteniev 89f90d9
reduce timeouts
AlexGuteniev 2bfa19a
fix `memcmp` race
AlexGuteniev 5471aad
optimize: check before waiting
AlexGuteniev 4266db1
newlines
AlexGuteniev 20356ed
Let's implement this in scope of atomic_ref
AlexGuteniev fbb3d11
clang format
AlexGuteniev df57ccd
don't need this if statically available
AlexGuteniev 7f57f6a
STL review: remove wrong const, add noexcept
AlexGuteniev fa295ec
tests complain
AlexGuteniev 61ec9fe
enforce barrier noexcept
AlexGuteniev 8922377
Merge remote-tracking branch 'origin/master' into latch
AlexGuteniev 04b9622
make semaphore test less sensitive to timing
AlexGuteniev 45b0923
Merge remote-tracking branch 'origin/master' into HEAD
BillyONeal 0968ed2
* Fix timeouts correctness bug wherein we would blow up the timeout o…
BillyONeal b4478b7
Add perf improvement special case for no timeout to reduce the number…
BillyONeal a832e67
Apply Stephan and Casey code review fixes.
BillyONeal fa0aaf6
Merge remote-tracking branch 'upstream/master' into latch
AlexGuteniev 3a9ece4
Merge remote-tracking branch 'origin/master' into latch
AlexGuteniev c9f9f4d
Remove const from unnamed function parameter
CaseyCarter 1212a8f
Semaphore counter optimization
AlexGuteniev e73081c
cover max count case with test
AlexGuteniev 7130a20
clang format
AlexGuteniev fdb5886
Merge remote-tracking branch 'upstream/master' into latch
AlexGuteniev ea2e773
fix merge error
AlexGuteniev 981556a
fix merge error
AlexGuteniev 1f1f2c3
ws
AlexGuteniev 4e90c42
Merge remote-tracking branch 'upstream/master'
AlexGuteniev cd4bfd4
remove timing assumption
AlexGuteniev f5ae641
latch test: assumption to finish in a finite time
AlexGuteniev 4e4be53
no <chrono> needed then
AlexGuteniev b8b7598
semaphore test: mask out timing assumption
AlexGuteniev 213e66b
16-bit type too
AlexGuteniev 560e237
GH-1133 workaround
AlexGuteniev 2fddcbf
typo
AlexGuteniev cf9e869
barrier check precondition better
AlexGuteniev 97276f4
Update stl/inc/semaphore
AlexGuteniev f934eeb
STL comments
AlexGuteniev 7057962
Merge branch 'latch'
AlexGuteniev 7efa65c
STL comments
AlexGuteniev d5b926f
Update tests/std/tests/P1135R6_semaphore/test.cpp
AlexGuteniev 8a2fcfc
Update tests/std/tests/P1135R6_semaphore/test.cpp
AlexGuteniev d768838
~
AlexGuteniev 1ad2d32
Merge branch 'latch' of https://github.com/AlexGuteniev/STL into latch
AlexGuteniev 7ddf346
:-(
AlexGuteniev 594147b
Update tests/libcxx/expected_results.txt
AlexGuteniev 1cd4bc6
Update tests/libcxx/skipped_tests.txt
AlexGuteniev 2240714
remove extra spaces
AlexGuteniev 6e2ef71
more STL comments
AlexGuteniev 8a4a9f2
Merge branch 'latch' of https://github.com/AlexGuteniev/STL into latch
AlexGuteniev 787a36a
clang format
AlexGuteniev b8cde5f
timing assumptions
AlexGuteniev 107c140
++
AlexGuteniev 6dbc25c
\
AlexGuteniev 22a1417
I speak Standardese
AlexGuteniev 60a6ada
prevent token reuse
AlexGuteniev 0dcd50f
optimize contended scenario
AlexGuteniev 893a1db
{
AlexGuteniev 8167828
!=
AlexGuteniev 9898469
avoid #1150
AlexGuteniev cdb907f
Precise wake count optimization
AlexGuteniev bead733
grammer
AlexGuteniev a3e8546
order
AlexGuteniev a497f2c
Revert "Precise wake count optimization"
AlexGuteniev cf4bf36
Precise wake count optimization
AlexGuteniev 5ecf1b0
+document
AlexGuteniev cda5f8a
private value
AlexGuteniev 961a5f8
comment on shift before pre check
AlexGuteniev 1d74f13
+ semaphore optimization for no waiters
AlexGuteniev 55c3cff
-
AlexGuteniev cafd052
more readable this way
AlexGuteniev ae60448
Resolves #1120
AlexGuteniev 90f1913
Revert "Resolves #1120"
AlexGuteniev 485311c
Merge remote-tracking branch 'upstream/master' into latch
AlexGuteniev a6235ad
This is now the last piece of P1135R6
AlexGuteniev 24ec0a5
less
AlexGuteniev 3ca997c
_Compressed_pair
AlexGuteniev a887830
Enforce least_max_value
AlexGuteniev b71e86d
Merge remote-tracking 'origin/master' into latch
AlexGuteniev acf2cb4
Merge remote-tracking 'upstream/master' into latch
AlexGuteniev 97bef22
Mention P1865R1
AlexGuteniev e337d66
noexcept /* strengthened */
AlexGuteniev 84f5ac6
barrier micro optimizations
AlexGuteniev f53c9e9
Update stl/inc/semaphore
AlexGuteniev 1c9192c
Update stl/inc/semaphore
AlexGuteniev 9ff64e2
move max
AlexGuteniev 26abe22
Merge branch 'latch' of https://github.com/AlexGuteniev/STL into latch
AlexGuteniev 499297d
@BillyONeal comments
AlexGuteniev 684f77b
token test
AlexGuteniev 0166140
more precise precondition
AlexGuteniev 9883201
memory order paranoia
AlexGuteniev a6900e4
comment on relaxed
AlexGuteniev a44a596
Merge remote-tracking branch 'origin/master' into latch
BillyONeal ae9e2a4
millisecondize
BillyONeal 3dfe326
Apply suggestions from code review
AlexGuteniev 326c18f
Update tests/std/tests/P1135R6_barrier/test.cpp
AlexGuteniev 0c2971a
Update tests/std/tests/P1135R6_barrier/test.cpp
AlexGuteniev File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,198 @@ | ||
| // barrier standard header | ||
|
|
||
| // Copyright (c) Microsoft Corporation. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|
|
||
| #pragma once | ||
| #ifndef _BARRIER_ | ||
| #define _BARRIER_ | ||
| #include <yvals.h> | ||
| #if _STL_COMPILER_PREPROCESSOR | ||
|
|
||
| #ifdef _M_CEE_PURE | ||
| #error <barrier> is not supported when compiling with /clr:pure. | ||
| #endif // _M_CEE_PURE | ||
|
|
||
| #if !_HAS_CXX20 | ||
| #pragma message("The contents of <barrier> are available only with C++20 or later.") | ||
| #else // ^^^ !_HAS_CXX20 / _HAS_CXX20 vvv | ||
|
|
||
| #include <atomic> | ||
| #include <limits.h> | ||
| #include <type_traits> | ||
| #include <xmemory> | ||
|
|
||
| #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 | ||
|
|
||
| _STD_BEGIN | ||
|
|
||
| struct _No_completion_function { | ||
| void operator()() noexcept {} | ||
| }; | ||
|
|
||
| template <class _Completion_function = _No_completion_function> | ||
| class barrier; | ||
|
|
||
| inline constexpr ptrdiff_t _Barrier_arrival_token_mask = 1; | ||
| inline constexpr ptrdiff_t _Barrier_value_mask = ~_Barrier_arrival_token_mask; | ||
| inline constexpr ptrdiff_t _Barrier_value_shift = 1; | ||
| inline constexpr ptrdiff_t _Barrier_invalid_token = 0; | ||
| inline constexpr ptrdiff_t _Barrier_value_step = 1 << _Barrier_value_shift; | ||
| inline constexpr ptrdiff_t _Barrier_max = (1ULL << (sizeof(ptrdiff_t) * CHAR_BIT - 2)) - 1; | ||
|
|
||
| template <class _Completion_function> | ||
| class _Arrival_token { | ||
| public: | ||
| _Arrival_token(_Arrival_token&& _Other) noexcept { | ||
| _Value = _Other._Value; | ||
| _Other._Value = _Barrier_invalid_token; | ||
| } | ||
|
|
||
| _Arrival_token& operator=(_Arrival_token&& _Other) noexcept { | ||
| _Value = _Other._Value; | ||
| _Other._Value = _Barrier_invalid_token; | ||
| return *this; | ||
| } | ||
|
|
||
| private: | ||
| explicit _Arrival_token(ptrdiff_t _Value_) noexcept : _Value(_Value_) {} | ||
| friend barrier<_Completion_function>; | ||
|
|
||
| ptrdiff_t _Value; | ||
| }; | ||
|
|
||
| template <class _Completion_function> | ||
| class barrier { | ||
| public: | ||
| static_assert( | ||
| #ifndef __cpp_noexcept_function_type | ||
BillyONeal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| is_function_v<remove_pointer_t<_Completion_function>> || | ||
| #endif // __cpp_noexcept_function_type | ||
| is_nothrow_invocable_v<_Completion_function&>, | ||
| "N4861 [thread.barrier.class]/5: is_nothrow_invocable_v<CompletionFunction&> shall be true"); | ||
|
|
||
| using arrival_token = _Arrival_token<_Completion_function>; | ||
|
|
||
| constexpr explicit barrier( | ||
| const ptrdiff_t _Expected, _Completion_function _Fn = _Completion_function()) noexcept /* strengthened */ | ||
| : _Val(_One_then_variadic_args_t{}, _STD move(_Fn), _Expected << _Barrier_value_shift) { | ||
| _STL_VERIFY(_Val._Myval2._Current.load(memory_order_relaxed) >= 0, | ||
| "Precondition: expected >= 0 and expected <= max() (N4861 [thread.barrier.class]/9)"); | ||
| } | ||
|
|
||
| barrier(const barrier&) = delete; | ||
| barrier& operator=(const barrier&) = delete; | ||
|
|
||
| _NODISCARD static constexpr ptrdiff_t(max)() noexcept { | ||
| return _Barrier_max; | ||
| } | ||
|
|
||
| _NODISCARD arrival_token arrive(ptrdiff_t _Update = 1) noexcept /* strengthened */ { | ||
| // Shifting before precondition check, so that exceeding max() will trigger precondition check too | ||
| _Update <<= _Barrier_value_shift; | ||
AlexGuteniev marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| _STL_VERIFY(_Update > 0, "Precondition: update > 0 (N4861 [thread.barrier.class]/12)"); | ||
| // TRANSITION, GH-1133: should be memory_order_release | ||
| ptrdiff_t _Current = _Val._Myval2._Current.fetch_sub(_Update) - _Update; | ||
| _STL_VERIFY(_Current >= 0, "Precondition: update is less than or equal to the expected count " | ||
| "for the current barrier phase (N4861 [thread.barrier.class]/12)"); | ||
| if ((_Current & _Barrier_value_mask) == 0) { | ||
| // TRANSITION, GH-1133: should have this fence: | ||
| // atomic_thread_fence(memory_order_acquire); | ||
| _Completion(_Current); | ||
| } | ||
| // Embedding this into the token to provide an additional correctness check that the token is from the same | ||
| // barrier and wasn't used. All bits of this fit, as barrier should be aligned to at least the size of an | ||
| // atomic counter. | ||
| return arrival_token{(_Current & _Barrier_arrival_token_mask) | reinterpret_cast<intptr_t>(this)}; | ||
AlexGuteniev marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| void wait(arrival_token&& _Arrival) const noexcept /* strengthened */ { | ||
| _STL_VERIFY((_Arrival._Value & _Barrier_value_mask) == reinterpret_cast<intptr_t>(this), | ||
| "Preconditions: arrival is associated with the phase synchronization point for the current phase " | ||
| "or the immediately preceding phase of the same barrier object (N4861 [thread.barrier.class]/19)"); | ||
| const ptrdiff_t _Arrival_value = _Arrival._Value & _Barrier_arrival_token_mask; | ||
| _Arrival._Value = _Barrier_invalid_token; | ||
| for (;;) { | ||
| // TRANSITION, GH-1133: should be memory_order_acquire | ||
| const ptrdiff_t _Current = _Val._Myval2._Current.load(); | ||
| _STL_VERIFY(_Current >= 0, "Invariant counter >= 0, possibly caused by preconditions violation " | ||
| "(N4861 [thread.barrier.class]/12)"); | ||
| if ((_Current & _Barrier_arrival_token_mask) != _Arrival_value) { | ||
| break; | ||
| } | ||
| _Val._Myval2._Current.wait(_Current, memory_order_relaxed); | ||
| } | ||
| } | ||
|
|
||
| void arrive_and_wait() noexcept /* strengthened */ { | ||
| // TRANSITION, GH-1133: should be memory_order_acq_rel | ||
| ptrdiff_t _Current = _Val._Myval2._Current.fetch_sub(_Barrier_value_step) - _Barrier_value_step; | ||
| const ptrdiff_t _Arrival = _Current & _Barrier_arrival_token_mask; | ||
| _STL_VERIFY(_Current >= 0, "Precondition: update is less than or equal to the expected count " | ||
| "for the current barrier phase (N4861 [thread.barrier.class]/12)"); | ||
| if ((_Current & _Barrier_value_mask) == 0) { | ||
| _Completion(_Current); | ||
| return; | ||
| } | ||
|
|
||
| for (;;) { | ||
| _Val._Myval2._Current.wait(_Current, memory_order_relaxed); | ||
| // TRANSITION, GH-1133: should be memory_order_acquire | ||
| _Current = _Val._Myval2._Current.load(); | ||
| _STL_VERIFY(_Current >= 0, "Invariant counter >= 0, possibly caused by preconditions violation " | ||
BillyONeal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "(N4861 [thread.barrier.class]/12)"); | ||
| if ((_Current & _Barrier_arrival_token_mask) != _Arrival) { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void arrive_and_drop() noexcept /* strengthened */ { | ||
| const ptrdiff_t _Rem_count = | ||
| _Val._Myval2._Total.fetch_sub(_Barrier_value_step, memory_order_relaxed) - _Barrier_value_step; | ||
| _STL_VERIFY(_Rem_count >= 0, "Precondition: The expected count for the current barrier phase " | ||
| "is greater than zero (N4861 [thread.barrier.class]/24) " | ||
| "(checked initial expected count, which is not less than the current)"); | ||
| (void) arrive(1); | ||
| } | ||
|
|
||
| private: | ||
| void _Completion(const ptrdiff_t _Current) noexcept { | ||
| const ptrdiff_t _Rem_count = _Val._Myval2._Total.load(memory_order_relaxed); | ||
BillyONeal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| _STL_VERIFY(_Rem_count >= 0, "Invariant: initial expected count less than zero, " | ||
| "possibly caused by preconditions violation " | ||
| "(N4861 [thread.barrier.class]/24)"); | ||
| _Val._Get_first()(); | ||
BillyONeal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| const ptrdiff_t _New_phase_count = _Rem_count | ((_Current + 1) & _Barrier_arrival_token_mask); | ||
| // TRANSITION, GH-1133: should be memory_order_release | ||
| _Val._Myval2._Current.store(_New_phase_count); | ||
| _Val._Myval2._Current.notify_all(); | ||
| } | ||
|
|
||
| struct _Counter_t { | ||
| constexpr explicit _Counter_t(ptrdiff_t _Initial) : _Current(_Initial), _Total(_Initial) {} | ||
| // wait(arrival_token&&) accepts a token from the current phase or the immediately preceding phase; this means | ||
| // we can track which phase is the current phase using 1 bit which alternates between each phase. For this | ||
| // purpose we use the low order bit of _Current. | ||
| atomic<ptrdiff_t> _Current; | ||
AlexGuteniev marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| atomic<ptrdiff_t> _Total; | ||
| }; | ||
|
|
||
| _Compressed_pair<_Completion_function, _Counter_t> _Val; | ||
| }; | ||
|
|
||
| _STD_END | ||
|
|
||
| #pragma pop_macro("new") | ||
| _STL_RESTORE_CLANG_WARNINGS | ||
| #pragma warning(pop) | ||
| #pragma pack(pop) | ||
| #endif // ^^^ _HAS_CXX20 ^^^ | ||
|
|
||
| #endif // _STL_COMPILER_PREPROCESSOR | ||
| #endif // _BARRIER_ | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| // latch standard header | ||
|
|
||
| // Copyright (c) Microsoft Corporation. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|
|
||
| #pragma once | ||
| #ifndef _LATCH_ | ||
| #define _LATCH_ | ||
| #include <yvals.h> | ||
| #if _STL_COMPILER_PREPROCESSOR | ||
|
|
||
| #ifdef _M_CEE_PURE | ||
| #error <latch> is not supported when compiling with /clr:pure. | ||
| #endif // _M_CEE_PURE | ||
|
|
||
| #if !_HAS_CXX20 | ||
| #pragma message("The contents of <latch> are available only with C++20 or later.") | ||
| #else // ^^^ !_HAS_CXX20 / _HAS_CXX20 vvv | ||
|
|
||
| #include <atomic> | ||
| #include <limits.h> | ||
|
|
||
| #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 | ||
|
|
||
| _STD_BEGIN | ||
|
|
||
| class latch { | ||
| public: | ||
| _NODISCARD static constexpr ptrdiff_t(max)() noexcept { | ||
| return (1ULL << (sizeof(ptrdiff_t) * CHAR_BIT - 1)) - 1; | ||
| } | ||
|
|
||
| constexpr explicit latch(const ptrdiff_t _Expected) noexcept /* strengthened */ : _Counter{_Expected} { | ||
| _STL_VERIFY(_Expected >= 0, "Precondition: expected >= 0 (N4861 [thread.latch.class]/4)"); | ||
BillyONeal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| latch(const latch&) = delete; | ||
| latch& operator=(const latch&) = delete; | ||
|
|
||
| void count_down(const ptrdiff_t _Update = 1) noexcept /* strengthened */ { | ||
| _STL_VERIFY(_Update >= 0, "Precondition: update >= 0 (N4861 [thread.latch.class]/7)"); | ||
| // TRANSITION, GH-1133: should be memory_order_release | ||
BillyONeal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| const ptrdiff_t _Current = _Counter.fetch_sub(_Update) - _Update; | ||
| if (_Current == 0) { | ||
| _Counter.notify_all(); | ||
| } else { | ||
| _STL_VERIFY(_Current >= 0, "Precondition: update <= counter (N4861 [thread.latch.class]/7)"); | ||
| } | ||
| } | ||
|
|
||
| _NODISCARD bool try_wait() const noexcept { | ||
| // TRANSITION, GH-1133: should be memory_order_acquire | ||
| return _Counter.load() == 0; | ||
| } | ||
|
|
||
| void wait() const noexcept /* strengthened */ { | ||
| for (;;) { | ||
| // TRANSITION, GH-1133: should be memory_order_acquire | ||
| const ptrdiff_t _Current = _Counter.load(); | ||
| if (_Current == 0) { | ||
| return; | ||
| } else { | ||
| _STL_VERIFY(_Current > 0, "Invariant counter >= 0, possibly caused by preconditions violation " | ||
| "(N4861 [thread.latch.class]/7)"); | ||
| } | ||
| _Counter.wait(_Current, memory_order_relaxed); | ||
| } | ||
| } | ||
|
|
||
| void arrive_and_wait(const ptrdiff_t _Update = 1) noexcept /* strengthened */ { | ||
| _STL_VERIFY(_Update >= 0, "Precondition: update >= 0 (N4861 [thread.latch.class]/7)"); | ||
| // TRANSITION, GH-1133: should be memory_order_acq_rel | ||
| const ptrdiff_t _Current = _Counter.fetch_sub(_Update) - _Update; | ||
| if (_Current == 0) { | ||
| _Counter.notify_all(); | ||
| } else { | ||
| _STL_VERIFY(_Current > 0, "Precondition: update <= counter (N4861 [thread.latch.class]/7)"); | ||
| _Counter.wait(_Current, memory_order_relaxed); | ||
| wait(); | ||
| } | ||
| } | ||
|
|
||
| private: | ||
| atomic<ptrdiff_t> _Counter; | ||
| }; | ||
|
|
||
| _STD_END | ||
|
|
||
| #pragma pop_macro("new") | ||
| _STL_RESTORE_CLANG_WARNINGS | ||
| #pragma warning(pop) | ||
| #pragma pack(pop) | ||
| #endif // ^^^ _HAS_CXX20 ^^^ | ||
|
|
||
| #endif // _STL_COMPILER_PREPROCESSOR | ||
| #endif // _LATCH_ | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.