diff --git a/libs/main/thread/piconditionvar.cpp b/libs/main/thread/piconditionvar.cpp index 9ad6538b..9480bb79 100644 --- a/libs/main/thread/piconditionvar.cpp +++ b/libs/main/thread/piconditionvar.cpp @@ -35,7 +35,6 @@ PRIVATE_DEFINITION_START(PIConditionVariable) CONDITION_VARIABLE nativeHandle; #else pthread_cond_t nativeHandle; - PIMutex * currentLock; #endif bool isDestroying; PRIVATE_DEFINITION_END(PIConditionVariable) @@ -46,9 +45,12 @@ PIConditionVariable::PIConditionVariable() { InitializeConditionVariable(&PRIVATE->nativeHandle); #else PRIVATE->isDestroying = false; - PRIVATE->currentLock = nullptr; - memset(&(PRIVATE->nativeHandle), 0, sizeof(PRIVATE->nativeHandle)); - pthread_cond_init(&PRIVATE->nativeHandle, NULL); + + pthread_condattr_t condattr; + pthread_condattr_init(&condattr); + pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC); + memset(&(PRIVATE->nativeHandle), 0, sizeof(PRIVATE->nativeHandle)); + pthread_cond_init(&PRIVATE->nativeHandle, &condattr); #endif } @@ -84,23 +86,38 @@ void PIConditionVariable::wait(PIMutex& lk, const std::function& conditi } } +void timespec_add_ms(timespec* ts, int ms) { + ts->tv_sec += ms / 1000; + ts->tv_nsec += ms % 1000 * 1000000; + if (ts->tv_nsec > 1000 * 1000 * 1000) { + ts->tv_sec++; + ts->tv_nsec -= 1000 * 1000 * 1000; + } +} bool PIConditionVariable::waitFor(PIMutex &lk, int timeoutMs) { bool isNotTimeout; #ifdef WINDOWS isNotTimeout = SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), timeoutMs) != 0; #else - timespec abstime = {.tv_sec = timeoutMs / 1000, .tv_nsec = timeoutMs % 1000 * 1000000}; - isNotTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &abstime) == 0; + timespec expire_ts; + clock_gettime(CLOCK_MONOTONIC, &expire_ts); + timespec_add_ms(&expire_ts, timeoutMs); + isNotTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &expire_ts) == 0; #endif if (PRIVATE->isDestroying) return false; return isNotTimeout; } - bool PIConditionVariable::waitFor(PIMutex& lk, int timeoutMs, const std::function &condition) { bool isCondition; +#ifdef WINDOWS PITimeMeasurer measurer; +#else + timespec expire_ts; + clock_gettime(CLOCK_MONOTONIC, &expire_ts); + timespec_add_ms(&expire_ts, timeoutMs); +#endif while (true) { isCondition = condition(); if (isCondition) break; @@ -110,9 +127,7 @@ bool PIConditionVariable::waitFor(PIMutex& lk, int timeoutMs, const std::functio (PCRITICAL_SECTION)lk.handle(), timeoutMs - (int)measurer.elapsed_m()) == 0; #else - int timeoutCurr = timeoutMs - (int)measurer.elapsed_m(); - timespec abstime = {.tv_sec = timeoutCurr / 1000, .tv_nsec = timeoutCurr % 1000 * 1000000}; - bool isTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &abstime) != 0; + bool isTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &expire_ts) != 0; #endif if (isTimeout) return false; if (PRIVATE->isDestroying) return false; diff --git a/tests/concurrent/BlockingDequeueUnitTest.cpp b/tests/concurrent/BlockingDequeueUnitTest.cpp index 993326dd..8c9c8818 100644 --- a/tests/concurrent/BlockingDequeueUnitTest.cpp +++ b/tests/concurrent/BlockingDequeueUnitTest.cpp @@ -14,9 +14,7 @@ public: void wait(PIMutex& lk, const std::function& condition) override { isWaitCalled = true; - lk.lock(); isTrueCondition = condition(); - lk.unlock(); } bool waitFor(PIMutex& lk, int timeoutMs) override { @@ -27,10 +25,8 @@ public: bool waitFor(PIMutex& lk, int timeoutMs, const std::function& condition) override { isWaitForCalled = true; - lk.lock(); isTrueCondition = condition(); timeout = timeoutMs; - lk.unlock(); return isTrueCondition; } };