From d348561aaf77f96aaa8c2454bce9b13b87f3cd29 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 27 Feb 2017 11:36:02 +0100 Subject: Use std::chrono::duration in Semaphore API --- NEWS | 4 ++-- raul/Semaphore.hpp | 52 +++++++++++++++++++++++++++++++++------------------- test/sem_test.cpp | 6 +++--- wscript | 2 +- 4 files changed, 39 insertions(+), 25 deletions(-) diff --git a/NEWS b/NEWS index f237d29..0c33fd9 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -raul (0.8.7) unstable; +raul (0.8.9) unstable; * Remove glib dpendency * Remove boost dependency @@ -14,7 +14,7 @@ raul (0.8.7) unstable; * Add INSTALL file * Update license to GPL3+ - -- David Robillard Sun, 12 Feb 2017 15:08:23 +0100 + -- David Robillard Mon, 27 Feb 2017 20:36:43 +0100 raul (0.8.0) stable; diff --git a/raul/Semaphore.hpp b/raul/Semaphore.hpp index 867e4be..d94da17 100644 --- a/raul/Semaphore.hpp +++ b/raul/Semaphore.hpp @@ -17,6 +17,7 @@ #ifndef RAUL_SEMAPHORE_HPP #define RAUL_SEMAPHORE_HPP +#include #include #ifdef __APPLE__ @@ -77,7 +78,8 @@ public: inline bool try_wait(); /** Wait for at most `ms` milliseconds. Return true iff decremented. */ - inline bool timed_wait(unsigned ms); + template + inline bool timed_wait(const std::chrono::duration& wait); private: inline bool init(unsigned initial); @@ -131,12 +133,17 @@ Semaphore::try_wait() return semaphore_timedwait(_sem, zero) == KERN_SUCCESS; } +template inline bool -Semaphore::timed_wait(unsigned ms) +Semaphore::timed_wait(const std::chrono::duration& wait) { - const unsigned s = ms / 1000; - const int nsec = ((int)ms - (s * 1000)) * 1000000; - const mach_timespec_t t = { s, nsec }; + namespace chr = std::chrono; + + const chr::seconds sec(chr::duration_cast(wait)); + const chr::nanoseconds nsec(wait - sec); + + const mach_timespec_t t = { static_cast(sec.count()), + static_cast(nsec.count()) }; return semaphore_timedwait(_sem, t) == KERN_SUCCESS; } @@ -178,10 +185,14 @@ Semaphore::try_wait() return WaitForSingleObject(_sem, 0) == WAIT_OBJECT_0; } +template inline bool -Semaphore::timed_wait(unsigned ms) +Semaphore::timed_wait(const std::chrono::duration& wait) { - return WaitForSingleObject(_sem, ms) == WAIT_OBJECT_0; + namespace chr = std::chrono; + + const chr::milliseconds ms(chr::duration_cast(wait)); + return WaitForSingleObject(_sem, ms.count()) == WAIT_OBJECT_0; } #else /* !defined(__APPLE__) && !defined(_WIN32) */ @@ -226,22 +237,25 @@ Semaphore::try_wait() return (sem_trywait(&_sem) == 0); } +template inline bool -Semaphore::timed_wait(unsigned ms) +Semaphore::timed_wait(const std::chrono::duration& wait) { - const unsigned seconds = ms / 1000; + namespace chr = std::chrono; - struct timespec now; - clock_gettime(CLOCK_REALTIME, &now); + // Use clock_gettime to ensure sem_timedwait uses the same clock + struct timespec time; + clock_gettime(CLOCK_REALTIME, &time); - struct timespec delta = { seconds, (ms - (seconds * 1000)) * 1000000 }; - struct timespec end = { now.tv_sec + delta.tv_sec, - now.tv_nsec + delta.tv_nsec }; - if (end.tv_nsec >= 1000000000L) { - ++end.tv_sec; - end.tv_nsec -= 1000000000L; - } - return (sem_timedwait(&_sem, &end) == 0); + const auto now(chr::seconds(time.tv_sec) + chr::nanoseconds(time.tv_nsec)); + const auto end(now + wait); + + const chr::seconds end_sec(chr::duration_cast(end)); + const chr::nanoseconds end_nsec(end - end_sec); + + const struct timespec ts_end = { end_sec.count(), end_nsec.count() }; + + return (sem_timedwait(&_sem, &ts_end) == 0); } #endif diff --git a/test/sem_test.cpp b/test/sem_test.cpp index 0400e38..453ba07 100644 --- a/test/sem_test.cpp +++ b/test/sem_test.cpp @@ -31,7 +31,7 @@ wait_for_sem(Raul::Semaphore* sem) static void timed_wait_for_sem(Raul::Semaphore* sem) { - while (!sem->timed_wait(100)) {} + while (!sem->timed_wait(std::chrono::milliseconds(100))) {} } int @@ -54,13 +54,13 @@ main() // Check that timed_wait actually waits const auto start = std::chrono::steady_clock::now(); - sem.timed_wait(100); + sem.timed_wait(std::chrono::milliseconds(100)); const auto end = std::chrono::steady_clock::now(); assert(end - start > std::chrono::milliseconds(100)); assert(end - start < std::chrono::milliseconds(200)); // Check that we can't successfully wait on a zero semaphore - assert(!sem.timed_wait(100)); + assert(!sem.timed_wait(std::chrono::milliseconds(100))); // Check that initial value works correctly sem = Raul::Semaphore(2); diff --git a/wscript b/wscript index 16ef9f4..cbd5c24 100644 --- a/wscript +++ b/wscript @@ -5,7 +5,7 @@ import waflib.Options as Options import waflib.extras.autowaf as autowaf # Version of this package (even if built as a child) -RAUL_VERSION = '0.8.7' +RAUL_VERSION = '0.8.9' # Library version (UNIX style major, minor, micro) # major increment <=> incompatible changes -- cgit v1.2.1