[PATCH v4 6/7] libstdc++ atomic_futex: Avoid rounding errors in std::future::wait_for
Mike Crowe
mac@mcrowe.com
Sun Oct 27 15:47:00 GMT 2019
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
More information about the Libstdc++
mailing list