On Sun, 14 Sept 2025 at 21:34, Mike Crowe <[email protected]> wrote:
>
> Add tests to show that std::condition_variable::wait_until and
> std::condition_variable::wait_for don't suffer from libstdc++/PR116586.
>
> libstdc++-v3/ChangeLog:
>
> * testsuite/30_threads/condition_variable/members/116586.c: New test.
>
> Signed-off-by: Mike Crowe <[email protected]>
> ---
> .../condition_variable/members/116586.cc | 58 +++++++++++++++++++
> 1 file changed, 58 insertions(+)
> create mode 100644
> libstdc++-v3/testsuite/30_threads/condition_variable/members/116586.cc
>
> diff --git
> a/libstdc++-v3/testsuite/30_threads/condition_variable/members/116586.cc
> b/libstdc++-v3/testsuite/30_threads/condition_variable/members/116586.cc
> new file mode 100644
> index 00000000000..d10f8036bb6
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/30_threads/condition_variable/members/116586.cc
> @@ -0,0 +1,58 @@
> +// { dg-do run { target c++11 } }
> +
> +#include <chrono>
> +#include <mutex>
> +#include <testsuite_hooks.h>
This is missing <condition_variable> (it works with the default build
config because every test gets the <bits/stdc++.h> PCH included).
Some of the other tests were missing <future>
> +
> +namespace chrono = std::chrono;
> +
> +// thread.timedmutex.requirements.general:
> +// If abs_time has already passed, the function attempts to obtain
> +// ownership without blocking (as if by calling try_lock()).
> +
> +template <typename Clock>
> +void
> +test_absolute(chrono::nanoseconds offset)
> +{
> + std::mutex mtx;
> + std::condition_variable cv;
> + chrono::time_point<Clock> tp(offset);
> + std::unique_lock lock(mtx);
This uses CTAD which isn't valid in C++11 and C++14. One of the tests
used CTAD for std::future too.
(And my suggestion to use chrono literals won't work in this file
either, as I'd forgotten they weren't added until C++14 - bah)
> + // Doesn't cope with spurious wakeup
> + VERIFY(cv.wait_until(lock, tp) == std::cv_status::timeout);
> +}
> +
> +// The type of clock used for the actual wait depends on whether
> +// _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK is defined. We might as well just
> test
> +// both steady_clock and system_clock.
> +template <typename Clock>
> +void
> +test_relative(chrono::nanoseconds offset)
> +{
> + std::mutex mtx;
> + std::condition_variable cv;
> + const auto d = -Clock::now().time_since_epoch() + offset;
> + std::unique_lock lock(mtx);
> + // Doesn't cope with spurious wakeup
> + VERIFY(cv.wait_for(lock, d) == std::cv_status::timeout);
> +}
> +
> +int main()
> +{
> + // It's not really possible to arrange for the relative calls to have
> + // tv_nsec == 0 due to time advancing.
> + for (const chrono::nanoseconds offset : {
> + // tv_sec == 0, tv_nsec == 0
> + chrono::nanoseconds{0},
> + // tv_sec == 0, tv_nsec < 0
> + chrono::duration_cast<chrono::nanoseconds>(chrono::milliseconds{-10}),
> + // tv_sec < 0
> + chrono::duration_cast<chrono::nanoseconds>(chrono::seconds{-10})
> + }) {
Apparently this needs <initializer_list> to be included to deduce the
{...} here.
I've made these changes locally when running the tests, so there's no
need for new patches - I'll get these pushed after I've pushed my one
with the utility functions for creating timespec.
> + test_absolute<chrono::system_clock>(offset);
> + test_relative<chrono::system_clock>(offset);
> +
> + test_absolute<chrono::steady_clock>(offset);
> + test_relative<chrono::steady_clock>(offset);
> + }
> +}
> --
> 2.39.5
>