This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] atomic_futex: Avoid rounding errors in std::future::wait_for
- From: Mike Crowe <mac at mcrowe dot com>
- To: libstdc++ at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Cc: Mike Crowe <mac at mcrowe dot com>
- Date: Thu, 2 Aug 2018 12:22:57 +0100
- Subject: [PATCH] atomic_futex: Avoid rounding errors in std::future::wait_for
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 | 6 +++++-
libstdc++-v3/testsuite/30_threads/async/async.cc | 15 +++++++++++++++
2 files changed, 20 insertions(+), 1 deletion(-)
This change depends on the some of the changes in the series I posted
yesterday. See https://gcc.gnu.org/ml/libstdc++/2018-08/msg00001.html
diff --git a/libstdc++-v3/include/bits/atomic_futex.h b/libstdc++-v3/include/bits/atomic_futex.h
index b7ffb7fb191..9703d752981 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 755c95cbea6..cd5113d5010 100644
--- a/libstdc++-v3/testsuite/30_threads/async/async.cc
+++ b/libstdc++-v3/testsuite/30_threads/async/async.cc
@@ -157,6 +157,20 @@ void test04()
}
}
+void test_pr36827()
+{
+ 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();
@@ -165,5 +179,6 @@ int main()
test03<std::chrono::steady_clock>();
test03<steady_clock_copy>();
test04();
+ test_pr36827();
return 0;
}
--
2.11.0