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

<semaphore>: Add missed mandates for counting_semaphore #3747

Merged
merged 3 commits into from
Jun 15, 2023
Merged
Changes from all commits
Commits
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
27 changes: 15 additions & 12 deletions stl/inc/semaphore
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ inline constexpr ptrdiff_t _Semaphore_max = (1ULL << (sizeof(ptrdiff_t) * CHAR_B
_EXPORT_STD template <ptrdiff_t _Least_max_value = _Semaphore_max>
class counting_semaphore {
public:
static_assert(_Least_max_value >= 0,
"The least maximum value for a counting_semaphore must be nonnegative (N4950 [thread.sema.cnt]/2).");
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved

_NODISCARD static constexpr ptrdiff_t(max)() noexcept {
return _Least_max_value;
}
Expand Down Expand Up @@ -90,8 +93,8 @@ public:
// memory_order_seq_cst might be superfluous for some hardware mappings of the C++ memory model,
// but from the point of view of the C++ memory model itself it is needed; weaker orders don't work.

const ptrdiff_t _Prev = _Counter.fetch_add(static_cast<ptrdiff_t>(_Update));
_STL_VERIFY(_Prev + _Update > 0 && _Prev + _Update <= _Least_max_value,
const ptrdiff_t _Prev = _Counter.fetch_add(_Update);
_STL_VERIFY(_Prev >= 0 && _Update <= _Least_max_value - _Prev,
"Precondition: update <= max() - counter (N4950 [thread.sema.cnt]/8)");

const ptrdiff_t _Waiting_upper_bound = _Waiting.load();
Expand All @@ -111,16 +114,6 @@ public:
}
}

void _Wait(const unsigned long _Remaining_timeout) noexcept {
// See the comment in release()
_Waiting.fetch_add(1);
ptrdiff_t _Current = _Counter.load();
if (_Current == 0) {
__std_atomic_wait_direct(&_Counter, &_Current, sizeof(_Current), _Remaining_timeout);
}
_Waiting.fetch_sub(1, memory_order_relaxed);
}

void acquire() noexcept /* strengthened */ {
ptrdiff_t _Current = _Counter.load(memory_order_relaxed);
for (;;) {
Expand Down Expand Up @@ -200,6 +193,16 @@ public:
}

private:
void _Wait(const unsigned long _Remaining_timeout) noexcept {
// See the comment in release()
_Waiting.fetch_add(1);
ptrdiff_t _Current = _Counter.load();
if (_Current == 0) {
__std_atomic_wait_direct(&_Counter, &_Current, sizeof(_Current), _Remaining_timeout);
}
_Waiting.fetch_sub(1, memory_order_relaxed);
}

atomic<ptrdiff_t> _Counter;
atomic<ptrdiff_t> _Waiting;
};
Expand Down