Convert the specified duration to the target clock's duration type before adding it to the current time. This avoids the situation described in PR libstdc++/68519 when the specified duration type lacks sufficient precision.
* libstdc++-v3/include/bits/atomic_futex.h: (__atomic_futex_unsigned::_M_load_when_equal_for): Round up timeout if required after conversion to reference clock duration. * libstdc++-v3/testsuite/30_threads/async/async.cc: (test_pr68519): New test for the equivalent of PR libstdc++/68519. --- libstdc++-v3/include/bits/atomic_futex.h | 6 +++++- libstdc++-v3/testsuite/30_threads/async/async.cc | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/libstdc++-v3/include/bits/atomic_futex.h b/libstdc++-v3/include/bits/atomic_futex.h index b04e806..ec823eb 100644 --- a/libstdc++-v3/include/bits/atomic_futex.h +++ b/libstdc++-v3/include/bits/atomic_futex.h @@ -219,8 +219,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_load_when_equal_for(unsigned __val, memory_order __mo, const chrono::duration<_Rep, _Period>& __rtime) { + using __dur = typename __clock_t::duration; + auto __reltime = chrono::duration_cast<__dur>(__rtime); + if (__reltime < __rtime) + ++__reltime; return _M_load_when_equal_until(__val, __mo, - __clock_t::now() + __rtime); + __clock_t::now() + __reltime); } // Returns false iff a timeout occurred. diff --git a/libstdc++-v3/testsuite/30_threads/async/async.cc b/libstdc++-v3/testsuite/30_threads/async/async.cc index 7700913..ddd007d 100644 --- a/libstdc++-v3/testsuite/30_threads/async/async.cc +++ b/libstdc++-v3/testsuite/30_threads/async/async.cc @@ -140,6 +140,20 @@ void test04() } } +void test_pr68519() +{ + future<void> f1 = async(launch::async, []() { + std::this_thread::sleep_for(std::chrono::seconds(1)); + }); + + std::chrono::duration<float> const wait_time = std::chrono::seconds(1); + auto const start_steady = chrono::steady_clock::now(); + auto status = f1.wait_for(wait_time); + auto const elapsed_steady = chrono::steady_clock::now() - start_steady; + + VERIFY( elapsed_steady >= std::chrono::seconds(1) ); +} + int main() { test01(); @@ -148,5 +162,6 @@ int main() test03<std::chrono::steady_clock>(); test03<slow_clock>(); test04(); + test_pr68519(); return 0; } -- git-series 0.9.1