This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[RFC PATCH 4/4] Extra async tests, not for merging
- 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: Fri, 22 Sep 2017 09:17:28 +0100
- Subject: [RFC PATCH 4/4] Extra async tests, not for merging
- Authentication-results: sourceware.org; auth=none
- References: <20170922081728.32508-1-mac@mcrowe.com>
These tests show that changing the system clock has an effect on
std::future::wait_until when using std::chrono::system_clock but not when
using std::chrono::steady_clock. Unfortunately these tests have a number of
downsides:
1. Nothing that is attempting to keep the clock set correctly (ntpd,
systemd-timesyncd) can be running at the same time.
2. The test process requires the CAP_SYS_TIME capability.
3. Other processes running concurrently may misbehave when the clock darts
back and forth.
4. They are slow to run.
As such, I don't think they are suitable for merging. I include them here
because I wanted to document how I had tested the changes in the previous
commits.
---
libstdc++-v3/testsuite/30_threads/async/async.cc | 76 ++++++++++++++++++++++++
1 file changed, 76 insertions(+)
diff --git a/libstdc++-v3/testsuite/30_threads/async/async.cc b/libstdc++-v3/testsuite/30_threads/async/async.cc
index 59905b4666f..0a3cb28fbda 100644
--- a/libstdc++-v3/testsuite/30_threads/async/async.cc
+++ b/libstdc++-v3/testsuite/30_threads/async/async.cc
@@ -25,6 +25,7 @@
#include <future>
#include <testsuite_hooks.h>
+#include <sys/time.h>
using namespace std;
@@ -94,11 +95,86 @@ void test03()
VERIFY( elapsed < std::chrono::seconds(20) );
}
+void perturb_system_clock(const std::chrono::seconds &seconds)
+{
+ struct timeval tv;
+ if (gettimeofday(&tv, NULL))
+ abort();
+
+ tv.tv_sec += seconds.count();
+ if (settimeofday(&tv, NULL))
+ abort();
+}
+
+void work04()
+{
+ std::this_thread::sleep_for(std::chrono::seconds(10));
+}
+
+// Ensure that advancing CLOCK_REALTIME doesn't make any difference
+// when we're waiting on std::chrono::steady_clock.
+void test04()
+{
+ auto const start = chrono::steady_clock::now();
+ future<void> f1 = async(launch::async, &work04);
+
+ perturb_system_clock(chrono::seconds(20));
+
+ std::future_status status;
+ status = f1.wait_for(std::chrono::seconds(4));
+ VERIFY( status == std::future_status::timeout );
+
+ status = f1.wait_until(start + std::chrono::seconds(6));
+ VERIFY( status == std::future_status::timeout );
+
+ status = f1.wait_until(start + std::chrono::seconds(12));
+ VERIFY( status == std::future_status::ready );
+
+ auto const elapsed = chrono::steady_clock::now() - start;
+ VERIFY( elapsed >= std::chrono::seconds(10) );
+ VERIFY( elapsed < std::chrono::seconds(15) );
+
+ perturb_system_clock(chrono::seconds(-20));
+}
+
+void work05()
+{
+ std::this_thread::sleep_for(std::chrono::seconds(5));
+ perturb_system_clock(chrono::seconds(60));
+ std::this_thread::sleep_for(std::chrono::seconds(5));
+}
+
+// Ensure that advancing CLOCK_REALTIME does make a difference when
+// we're waiting on std::chrono::system_clock.
+void test05()
+{
+ auto const start = chrono::system_clock::now();
+ auto const start_steady = chrono::steady_clock::now();
+
+ future<void> f1 = async(launch::async, &work05);
+ future_status status;
+ status = f1.wait_until(start + std::chrono::seconds(60));
+ VERIFY( status == std::future_status::timeout );
+
+ auto const elapsed_steady = chrono::steady_clock::now() - start_steady;
+ VERIFY( elapsed_steady >= std::chrono::seconds(5) );
+ VERIFY( elapsed_steady < std::chrono::seconds(10) );
+
+ status = f1.wait_until(start + std::chrono::seconds(75));
+ VERIFY( status == std::future_status::ready );
+
+ perturb_system_clock(chrono::seconds(-60));
+}
+
int main()
{
test01();
test02();
test03<std::chrono::system_clock>();
test03<std::chrono::steady_clock>();
+ if (geteuid() == 0) {
+ test04();
+ test05();
+ }
return 0;
}
--
2.11.0