about summary refs log tree commit diff
path: root/src/rt/sync
diff options
context:
space:
mode:
Diffstat (limited to 'src/rt/sync')
-rw-r--r--src/rt/sync/lock_and_signal.cpp34
-rw-r--r--src/rt/sync/lock_and_signal.h5
2 files changed, 34 insertions, 5 deletions
diff --git a/src/rt/sync/lock_and_signal.cpp b/src/rt/sync/lock_and_signal.cpp
index 3d0d1013889..f4c3778837d 100644
--- a/src/rt/sync/lock_and_signal.cpp
+++ b/src/rt/sync/lock_and_signal.cpp
@@ -10,7 +10,9 @@
 #include "lock_and_signal.h"
 
 #if defined(__WIN32__)
-lock_and_signal::lock_and_signal() {
+lock_and_signal::lock_and_signal() 
+    : alive(true)
+{
     // FIXME: In order to match the behavior of pthread_cond_broadcast on
     // Windows, we create manual reset events. This however breaks the
     // behavior of pthread_cond_signal, fixing this is quite involved:
@@ -22,7 +24,7 @@ lock_and_signal::lock_and_signal() {
 
 #else
 lock_and_signal::lock_and_signal()
-    : _locked(false)
+    : _locked(false), alive(true)
 {
     CHECKED(pthread_cond_init(&_cond, NULL));
     CHECKED(pthread_mutex_init(&_mutex, NULL));
@@ -36,6 +38,7 @@ lock_and_signal::~lock_and_signal() {
     CHECKED(pthread_cond_destroy(&_cond));
     CHECKED(pthread_mutex_destroy(&_mutex));
 #endif
+    alive = false;
 }
 
 void lock_and_signal::lock() {
@@ -65,11 +68,14 @@ void lock_and_signal::wait() {
     timed_wait(0);
 }
 
-void lock_and_signal::timed_wait(size_t timeout_in_ns) {
+bool lock_and_signal::timed_wait(size_t timeout_in_ns) {
+    _locked = false;
+    bool rv = true;
 #if defined(__WIN32__)
     LeaveCriticalSection(&_cs);
     WaitForSingleObject(_event, INFINITE);
     EnterCriticalSection(&_cs);
+    _holding_thread = GetCurrentThreadId();
 #else
     if (timeout_in_ns == 0) {
         CHECKED(pthread_cond_wait(&_cond, &_mutex));
@@ -79,9 +85,29 @@ void lock_and_signal::timed_wait(size_t timeout_in_ns) {
         timespec time_spec;
         time_spec.tv_sec = time_val.tv_sec + 0;
         time_spec.tv_nsec = time_val.tv_usec * 1000 + timeout_in_ns;
-        CHECKED(pthread_cond_timedwait(&_cond, &_mutex, &time_spec));
+        if(time_spec.tv_nsec >= 1000000000) {
+            time_spec.tv_sec++;
+            time_spec.tv_nsec -= 1000000000;
+        }
+        int cond_wait_status
+            = pthread_cond_timedwait(&_cond, &_mutex, &time_spec);
+        switch(cond_wait_status) {
+        case 0:
+            // successfully grabbed the lock.
+            break;
+        case ETIMEDOUT:
+            // Oops, we timed out.
+            rv = false;
+            break;
+        default:
+            // Error
+            CHECKED(cond_wait_status);
+        }
     }
+    _holding_thread = pthread_self();
 #endif
+    _locked = true;
+    return rv;
 }
 
 /**
diff --git a/src/rt/sync/lock_and_signal.h b/src/rt/sync/lock_and_signal.h
index 60c22958342..6e656017115 100644
--- a/src/rt/sync/lock_and_signal.h
+++ b/src/rt/sync/lock_and_signal.h
@@ -14,6 +14,9 @@ class lock_and_signal {
     pthread_t _holding_thread;
 #endif
     bool _locked;
+
+    bool alive;
+
 public:
     lock_and_signal();
     virtual ~lock_and_signal();
@@ -21,7 +24,7 @@ public:
     void lock();
     void unlock();
     void wait();
-    void timed_wait(size_t timeout_in_ns);
+    bool timed_wait(size_t timeout_in_ns);
     void signal();
     void signal_all();