From 83fd5e73b3c16296e0d7ba54f6c547e01c7eae7b Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 14 Dec 2017 20:41:52 +0000 Subject: [PATCH] PR libstdc++/68519 use native duration to avoid rounding errors PR libstdc++/68519 * include/std/condition_variable (condition_variable::wait_for): Convert duration to native clock's duration before addition. * testsuite/30_threads/condition_variable/members/68519.cc: New test. From-SVN: r255665 --- libstdc++-v3/ChangeLog | 5 ++ libstdc++-v3/include/std/condition_variable | 16 +++++- .../condition_variable/members/68519.cc | 51 +++++++++++++++++++ 3 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 libstdc++-v3/testsuite/30_threads/condition_variable/members/68519.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 143739f1ce2..9f2eff11623 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,10 @@ 2017-12-14 Jonathan Wakely + PR libstdc++/68519 + * include/std/condition_variable (condition_variable::wait_for): + Convert duration to native clock's duration before addition. + * testsuite/30_threads/condition_variable/members/68519.cc: New test. + PR libstdc++/83427 * include/bits/refwrap.h (_Maybe_unary_or_binary_function): Move here from . diff --git a/libstdc++-v3/include/std/condition_variable b/libstdc++-v3/include/std/condition_variable index 1d8f057ceb6..6d20d365531 100644 --- a/libstdc++-v3/include/std/condition_variable +++ b/libstdc++-v3/include/std/condition_variable @@ -135,14 +135,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION cv_status wait_for(unique_lock& __lock, const chrono::duration<_Rep, _Period>& __rtime) - { return wait_until(__lock, __clock_t::now() + __rtime); } + { + using __dur = typename __clock_t::duration; + auto __reltime = chrono::duration_cast<__dur>(__rtime); + if (__reltime < __rtime) + ++__reltime; + return wait_until(__lock, __clock_t::now() + __reltime); + } template bool wait_for(unique_lock& __lock, const chrono::duration<_Rep, _Period>& __rtime, _Predicate __p) - { return wait_until(__lock, __clock_t::now() + __rtime, std::move(__p)); } + { + using __dur = typename __clock_t::duration; + auto __reltime = chrono::duration_cast<__dur>(__rtime); + if (__reltime < __rtime) + ++__reltime; + return wait_until(__lock, __clock_t::now() + __reltime, std::move(__p)); + } native_handle_type native_handle() diff --git a/libstdc++-v3/testsuite/30_threads/condition_variable/members/68519.cc b/libstdc++-v3/testsuite/30_threads/condition_variable/members/68519.cc new file mode 100644 index 00000000000..71c1d29e231 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/condition_variable/members/68519.cc @@ -0,0 +1,51 @@ +// Copyright (C) 2017 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 +// . + +// { dg-do run } +// { dg-options "-pthread" } +// { dg-require-effective-target c++11 } +// { dg-require-effective-target pthread } +// { dg-require-cstdint "" } +// { dg-require-gthreads "" } + +#include +#include + +// PR libstdc++/68519 + +bool val = false; +std::mutex mx; +std::condition_variable cv; + +void +test01() +{ + for (int i = 0; i < 3; ++i) + { + std::unique_lock l(mx); + auto start = std::chrono::system_clock::now(); + cv.wait_for(l, std::chrono::duration(1), [] { return val; }); + auto t = std::chrono::system_clock::now(); + VERIFY( (t - start) >= std::chrono::seconds(1) ); + } +} + +int +main() +{ + test01(); +} -- 2.30.2