diff options
author | Dan Albert <danalbert@google.com> | 2019-09-16 17:57:48 +0000 |
---|---|---|
committer | Dan Albert <danalbert@google.com> | 2019-09-16 17:57:48 +0000 |
commit | 5e37d7f9ff257ec62d733d3d94b11f03e0fe51ca (patch) | |
tree | f4af4ede926be38fda3e28290cb730b12d6faa81 /libcxx/test/std/thread | |
parent | 6fcd4e080f09c9765d6e0ea03b1da91669c8509a (diff) | |
download | bcm5719-llvm-5e37d7f9ff257ec62d733d3d94b11f03e0fe51ca.tar.gz bcm5719-llvm-5e37d7f9ff257ec62d733d3d94b11f03e0fe51ca.zip |
Implement std::condition_variable via pthread_cond_clockwait() where available
std::condition_variable is currently implemented via
pthread_cond_timedwait() on systems that use pthread. This is
problematic, since that function waits by default on CLOCK_REALTIME
and libc++ does not provide any mechanism to change from this
default.
Due to this, regardless of if condition_variable::wait_until() is
called with a chrono::system_clock or chrono::steady_clock parameter,
condition_variable::wait_until() will wait using CLOCK_REALTIME. This
is not accurate to the C++ standard as calling
condition_variable::wait_until() with a chrono::steady_clock parameter
should use CLOCK_MONOTONIC.
This is particularly problematic because CLOCK_REALTIME is a bad
choice as it is subject to discontinuous time adjustments, that may
cause condition_variable::wait_until() to immediately timeout or wait
indefinitely.
This change fixes this issue with a new POSIX function,
pthread_cond_clockwait() proposed on
http://austingroupbugs.net/view.php?id=1216. The new function is
similar to pthread_cond_timedwait() with the addition of a clock
parameter that allows it to wait using either CLOCK_REALTIME or
CLOCK_MONOTONIC, thus allowing condition_variable::wait_until() to
wait using CLOCK_REALTIME for chrono::system_clock and CLOCK_MONOTONIC
for chrono::steady_clock.
pthread_cond_clockwait() is implemented in glibc (2.30 and later) and
Android's bionic (Android API version 30 and later).
This change additionally makes wait_for() and wait_until() with clocks
other than chrono::system_clock use CLOCK_MONOTONIC.<Paste>
llvm-svn: 372016
Diffstat (limited to 'libcxx/test/std/thread')
-rw-r--r-- | libcxx/test/std/thread/thread.condition/thread.condition.condvar/wait_until.pass.cpp | 33 |
1 files changed, 22 insertions, 11 deletions
diff --git a/libcxx/test/std/thread/thread.condition/thread.condition.condvar/wait_until.pass.cpp b/libcxx/test/std/thread/thread.condition/thread.condition.condvar/wait_until.pass.cpp index 12ccf3f1c06..e5c77f28eb8 100644 --- a/libcxx/test/std/thread/thread.condition/thread.condition.condvar/wait_until.pass.cpp +++ b/libcxx/test/std/thread/thread.condition/thread.condition.condvar/wait_until.pass.cpp @@ -25,12 +25,12 @@ #include "test_macros.h" -struct Clock +struct TestClock { typedef std::chrono::milliseconds duration; typedef duration::rep rep; typedef duration::period period; - typedef std::chrono::time_point<Clock> time_point; + typedef std::chrono::time_point<TestClock> time_point; static const bool is_steady = true; static time_point now() @@ -50,35 +50,40 @@ int test2 = 0; int runs = 0; +template <typename Clock> void f() { std::unique_lock<std::mutex> lk(mut); assert(test2 == 0); test1 = 1; cv.notify_one(); - Clock::time_point t0 = Clock::now(); - Clock::time_point t = t0 + Clock::duration(250); + typename Clock::time_point t0 = Clock::now(); + typename Clock::time_point t = t0 + std::chrono::milliseconds(250); while (test2 == 0 && cv.wait_until(lk, t) == std::cv_status::no_timeout) ; - Clock::time_point t1 = Clock::now(); + typename Clock::time_point t1 = Clock::now(); if (runs == 0) { - assert(t1 - t0 < Clock::duration(250)); + assert(t1 - t0 < std::chrono::milliseconds(250)); assert(test2 != 0); } else { - assert(t1 - t0 - Clock::duration(250) < Clock::duration(50)); + assert(t1 - t0 - std::chrono::milliseconds(250) < std::chrono::milliseconds(50)); assert(test2 == 0); } ++runs; } -int main(int, char**) +template <typename Clock> +void run_test() { + runs = 0; + test1 = 0; + test2 = 0; { std::unique_lock<std::mutex>lk(mut); - std::thread t(f); + std::thread t(f<Clock>); assert(test1 == 0); while (test1 == 0) cv.wait(lk); @@ -92,7 +97,7 @@ int main(int, char**) test2 = 0; { std::unique_lock<std::mutex>lk(mut); - std::thread t(f); + std::thread t(f<Clock>); assert(test1 == 0); while (test1 == 0) cv.wait(lk); @@ -100,6 +105,12 @@ int main(int, char**) lk.unlock(); t.join(); } +} - return 0; +int main(int, char**) +{ + run_test<TestClock>(); + run_test<std::chrono::steady_clock>(); + run_test<std::chrono::system_clock>(); + return 0; } |