[libc++] add basic runtime assertions to <latch>

Adding assertions will aid users that have bugs in their code to
receive better error messages.

Differential Revision: https://reviews.llvm.org/D154425
This commit is contained in:
Edoardo Sanguineti 2023-07-05 17:33:18 -04:00 committed by Louis Dionne
parent 20964c901a
commit 5e807c38bf
4 changed files with 139 additions and 2 deletions

View File

@ -75,7 +75,15 @@ public:
}
inline _LIBCPP_INLINE_VISIBILITY
constexpr explicit latch(ptrdiff_t __expected) : __a_(__expected) { }
constexpr explicit latch(ptrdiff_t __expected) : __a_(__expected)
{
_LIBCPP_ASSERT_UNCATEGORIZED(__expected >= 0,
"latch::latch(ptrdiff_t): latch cannot be "
"initialized with a negative value");
_LIBCPP_ASSERT_UNCATEGORIZED(__expected <= max(),
"latch::latch(ptrdiff_t): latch cannot be "
"initialized with a value greater than max()");
}
_LIBCPP_HIDE_FROM_ABI ~latch() = default;
latch(const latch&) = delete;
@ -84,8 +92,13 @@ public:
inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
void count_down(ptrdiff_t __update = 1)
{
_LIBCPP_ASSERT_UNCATEGORIZED(
__update >= 0, "latch::count_down called with a negative value");
auto const __old = __a_.fetch_sub(__update, memory_order_release);
if(__old == __update)
_LIBCPP_ASSERT_UNCATEGORIZED(
__update <= __old, "latch::count_down called with a value greater "
"than the internal counter");
if (__old == __update)
__a_.notify_all();
}
inline _LIBCPP_INLINE_VISIBILITY
@ -103,6 +116,10 @@ public:
inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
void arrive_and_wait(ptrdiff_t __update = 1)
{
_LIBCPP_ASSERT_UNCATEGORIZED(
__update >= 0, "latch::arrive_and_wait called with a negative value");
// other preconditions on __update are checked in count_down()
count_down(__update);
wait();
}

View File

@ -0,0 +1,37 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: no-threads
// UNSUPPORTED: c++03, c++11, c++14, c++17
// <latch>
// class latch;
// void arrive_and_wait(ptrdiff_t __update = 1);
// Make sure that calling arrive_and_wait with a negative value triggers an assertion.
// REQUIRES: has-unix-headers
// XFAIL: availability-verbose_abort-missing
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <latch>
#include "check_assertion.h"
int main(int, char **) {
{
std::latch l(5);
TEST_LIBCPP_ASSERT_FAILURE(
l.arrive_and_wait(-10),
"latch::arrive_and_wait called with a negative value");
}
return 0;
}

View File

@ -0,0 +1,45 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: no-threads
// UNSUPPORTED: c++03, c++11, c++14, c++17
// <latch>
// class latch;
// void count_down(ptrdiff_t __update = 1);
// Make sure that calling count_down with a negative value or a value
// higher than the internal counter triggers an assertion.
// REQUIRES: has-unix-headers
// XFAIL: availability-verbose_abort-missing
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <latch>
#include "check_assertion.h"
int main(int, char **) {
{
std::latch l(5);
TEST_LIBCPP_ASSERT_FAILURE(
l.count_down(-10), "latch::count_down called with a negative value");
}
{
std::latch l(5);
TEST_LIBCPP_ASSERT_FAILURE(l.count_down(10),
"latch::count_down called with a value greater "
"than the internal counter");
}
return 0;
}

View File

@ -0,0 +1,38 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: no-threads
// UNSUPPORTED: c++03, c++11, c++14, c++17
// <latch>
// class latch;
// constexpr explicit latch(ptrdiff_t __expected);
// Make sure that calling latch with a negative value triggers an assertion
// REQUIRES: has-unix-headers
// XFAIL: availability-verbose_abort-missing
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1
#include <latch>
#include "check_assertion.h"
int main(int, char **) {
{
TEST_LIBCPP_ASSERT_FAILURE([]{ std::latch l(-1); }(),
"latch::latch(ptrdiff_t): latch cannot be "
"initialized with a negative value");
}
// We can't check the precondition for max() because there's no value
// that would violate the precondition (in our implementation)
return 0;
}