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 --- raul/Semaphore.hpp | 52 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 19 deletions(-) (limited to 'raul/Semaphore.hpp') 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 -- cgit v1.2.1