1. Introduction
During the wording review of the C++20 Synchronization Library, [P1135R4], four design flaws were found in the paper. Rather than send the entire paper back to SG1 to look over the changes and risk missing the deadline for C++20, this new paper is being written for SG1 to review.
The wording changes here have already been applied to [P1135R5]. If SG1 approves these changes, then P1135 will go to LWG in its current state. If any of the changes are rejected by SG1, then the change will be backed out of P1135, by applying the wording change in this paper in reverse, before LWG gives its final approval to P1135.
2. Changelog
Revision 0: Initial version.
3. Make atomic_flag::test const
3.1. Motivation
does not modify the
object at all,
so it should be a
member function. Similarly, the first
parameter to
and
should
be of type
or
.
This bug seems to have been here from the beginning. See [P0995R0]. There is no record of a discussion of the const-ness of these functions.
3.2. Wording
Modify the header synopsis for
in [atomics.syn] as follows:
// 30.9, flag type and operations struct atomic_flag ; bool atomic_flag_test ( const volatile atomic_flag * ) noexcept ; bool atomic_flag_test ( const atomic_flag * ) noexcept ; bool atomic_flag_test_explicit ( const volatile atomic_flag * , memory_order ) noexcept ; bool atomic_flag_test_explicit ( const atomic_flag * , memory_order ) noexcept ;
Modify [atomics.flag] as follows:
30.9 Flag type and operations [atomics.flag]
namespace std { struct atomic_flag { bool test ( memory_order = memory_order :: seq_cst ) const volatile noexcept ; bool test ( memory_order = memory_order :: seq_cst ) const noexcept ; // ... }; bool atomic_flag_test ( const volatile atomic_flag * ) noexcept ; bool atomic_flag_test ( const atomic_flag * ) noexcept ; bool atomic_flag_test_explicit ( const volatile atomic_flag * , memory_order ) noexcept ; bool atomic_flag_test_explicit ( const atomic_flag * , memory_order ) noexcept ; //... }
Still within section [atomics.flag], change the function signatures between paragraph 4 and paragraph 5 as follows:
bool atomic_flag_test ( const volatile atomic_flag * object ) noexcept ; bool atomic_flag_test ( const atomic_flag * object ) noexcept ; bool atomic_flag_test_explicit ( const volatile atomic_flag * object , memory_order order ) noexcept ; bool atomic_flag_test_explicit ( const atomic_flag * object , memory_order order ) noexcept ; bool atomic_flag :: test ( memory_order order = memory_order :: seq_cst ) const volatile noexcept ; bool atomic_flag :: test ( memory_order order = memory_order :: seq_cst ) const noexcept ;
4. Prohibit counting_semaphore<-1>
4.1. Motivation
template < ptrdiff_t least_max_value = implementation - defined >
class counting_semaphore ;
Template class
has a non-type template parameter
which is intended to put an upper limit on the number
of times a semaphore of that type can be simultaneously acquired.
[P1135R3] had no restrictions on the value of
.
There was nothing that prevented users from using
or
, neither of which
can do anything useful.
4.2. Wording
Insert a new paragraph after paragraph 1 in [thread.semaphore.counting.class]:
shall be greater than zero; otherwise the program is ill-formed.
least_max_value
5. Prohibit barrier::arrive(0)
5.1. Motivation
[P0666R2] and early versions of P1135 did not put any lower limit on the
value of the
parameter for
.
While working on [P1135R4], wording was added to require that
, since negative values don’t make sense. During LWG
wording review in Kona, Dan Sunderland pointed out that
would be problematic for implementations that used
a fan-in strategy rather than a counter, since it would allow threads
to wait on the barrier without arriving at the barrier.
is
of dubious usefulness even without the implementation problem, so the
lower bound of
is changed from zero to one, making
undefined behavior, the same as
.
5.2. Wording
Change paragraph 13 in [thread.coord.barrier.class] as follows:
[[ nodiscard ]] arrival_token arrive ( ptrdiff_t update = 1 ); Expects:is
update >= > 0 true
, andis less than or equal to the expected count for the current barrier phase.
update
6. Allow latch::try_wait() to fail spuriously
6.1. Motivation
The old wording for
of "Returns:
" implied that implementations needed to use
for
so that
would immediately see the result of a different thread’s call to
. The new wording that allows
to spuriously return false
frees the implementation to use a more relaxed memory order.
6.2. Wording
Change paragraph 13 in [thread.coord.latch.class] as follows:
bool try_wait () const noexcept ; Returns: With very low probabilityfalse
. Otherwise
counter == 0