blob: 56db2b5f0371ad741a0b59e69e617484be2d900e [file] [log] [blame]
// Copyright (C) 2017-2021 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-do run }
// { dg-additional-options "-pthread" { target pthread } }
// { dg-require-effective-target c++11 }
// { dg-require-gthreads "" }
#include <condition_variable>
#include <testsuite_hooks.h>
// PR libstdc++/68519
void
test_wait_for()
{
std::mutex mx;
std::condition_variable cv;
for (int i = 0; i < 3; ++i)
{
std::unique_lock<std::mutex> l(mx);
auto start = std::chrono::system_clock::now();
cv.wait_for(l, std::chrono::duration<float>(1), [] { return false; });
auto t = std::chrono::system_clock::now();
VERIFY( (t - start) >= std::chrono::seconds(1) );
}
}
// In order to ensure that the delta calculated in the arbitrary clock overload
// of condition_variable::wait_until fits accurately in a float, but the result
// of adding it to steady_clock with a float duration does not, this clock
// needs to use a more recent epoch.
struct recent_epoch_float_clock
{
using duration = std::chrono::duration<float>;
using rep = duration::rep;
using period = duration::period;
using time_point
= std::chrono::time_point<recent_epoch_float_clock, duration>;
static constexpr bool is_steady = true;
static const std::chrono::steady_clock::time_point epoch;
static time_point now()
{
const auto steady = std::chrono::steady_clock::now();
return time_point{steady - epoch};
}
};
const std::chrono::steady_clock::time_point recent_epoch_float_clock::epoch =
std::chrono::steady_clock::now();
void
test_wait_until()
{
using clock = recent_epoch_float_clock;
std::mutex mx;
std::condition_variable cv;
for (int i = 0; i < 3; ++i)
{
std::unique_lock<std::mutex> l(mx);
const auto start = clock::now();
const auto wait_time = start + std::chrono::duration<float>{1.0};
// In theory we could get a spurious wakeup, but in practice we won't.
const auto result = cv.wait_until(l, wait_time);
VERIFY( result == std::cv_status::timeout );
const auto elapsed = clock::now() - start;
VERIFY( elapsed >= std::chrono::seconds(1) );
}
}
int
main()
{
test_wait_for();
test_wait_until();
}