summaryrefslogtreecommitdiff
path: root/src/semaphore.cc
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2016-04-24 21:39:16 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2016-04-24 21:39:41 +0200
commit32463cb2f19c0f1af4edddb396f9ea0abf5147e5 (patch)
tree5e1406f846d0ff3829ff3db7d1664fe4ec543680 /src/semaphore.cc
parentec9f9cfe169f7fca3083b5792f9d72dbf3af7f08 (diff)
Fix broken timed_wait implementation.
Diffstat (limited to 'src/semaphore.cc')
-rw-r--r--src/semaphore.cc26
1 files changed, 19 insertions, 7 deletions
diff --git a/src/semaphore.cc b/src/semaphore.cc
index 6172251..ea88456 100644
--- a/src/semaphore.cc
+++ b/src/semaphore.cc
@@ -29,6 +29,7 @@
#include <hugin.hpp>
#include <limits>
#include <assert.h>
+#include <string.h>
#ifdef WIN32
#include <windows.h>
@@ -58,6 +59,7 @@ Semaphore::Semaphore(std::size_t initial_count)
nullptr); // unnamed semaphore
#else
const int pshared = 0;
+ memset(&prv->semaphore, 0, sizeof(sem_t));
sem_init(&prv->semaphore, pshared, initial_count);
#endif
}
@@ -93,15 +95,25 @@ bool Semaphore::wait(const std::chrono::milliseconds& timeout)
assert(ret == WAIT_OBJECT_0);
#else
- struct timespec t = {
- // Whole seconds:
- (time_t)(timeout.count() / 1000),
+ struct timespec ts;
- // Remainder as nanoseconds:
- (long)((timeout.count() - ((timeout.count() / 1000) * 1000)) * 1000000)
- };
+ // Get current time
+ clock_gettime(CLOCK_REALTIME, &ts);
- int ret = sem_timedwait(&prv->semaphore, &t);
+ // Add timeout
+ time_t seconds = (time_t)(timeout.count() / 1000);
+ ts.tv_sec += seconds;
+ ts.tv_nsec += (long)((timeout.count() - (seconds * 1000)) * 1000000);
+
+ // Make sure we don't overflow the nanoseconds.
+ constexpr long nsec = 1000000000LL;
+ if(ts.tv_nsec >= nsec)
+ {
+ ts.tv_nsec -= nsec;
+ ts.tv_sec += 1;
+ }
+
+ int ret = sem_timedwait(&prv->semaphore, &ts);
if(ret < 0)
{
if(errno == ETIMEDOUT)