blob: e8c3e1634e27270af23ebc953e61e49a3da8854a [file] [log] [blame]
// { dg-do run { target c++11 } }
// { dg-additional-options "-pthread" { target pthread } }
// { dg-require-gthreads "" }
// { dg-require-effective-target hosted }
#include <condition_variable>
#include <chrono>
#include <mutex>
#include <initializer_list>
#include <testsuite_hooks.h>
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<std::mutex> lock(mtx);
// 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<std::mutex> 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})
}) {
test_absolute<chrono::system_clock>(offset);
test_relative<chrono::system_clock>(offset);
test_absolute<chrono::steady_clock>(offset);
test_relative<chrono::steady_clock>(offset);
}
}