Fix waitFor timeout behaviour

This commit is contained in:
2 changed files with 25 additions and 14 deletions

View File

@@ -35,7 +35,6 @@ PRIVATE_DEFINITION_START(PIConditionVariable)
CONDITION_VARIABLE nativeHandle; CONDITION_VARIABLE nativeHandle;
#else #else
pthread_cond_t nativeHandle; pthread_cond_t nativeHandle;
PIMutex * currentLock;
#endif #endif
bool isDestroying; bool isDestroying;
PRIVATE_DEFINITION_END(PIConditionVariable) PRIVATE_DEFINITION_END(PIConditionVariable)
@@ -46,9 +45,12 @@ PIConditionVariable::PIConditionVariable() {
InitializeConditionVariable(&PRIVATE->nativeHandle); InitializeConditionVariable(&PRIVATE->nativeHandle);
#else #else
PRIVATE->isDestroying = false; PRIVATE->isDestroying = false;
PRIVATE->currentLock = nullptr;
memset(&(PRIVATE->nativeHandle), 0, sizeof(PRIVATE->nativeHandle)); pthread_condattr_t condattr;
pthread_cond_init(&PRIVATE->nativeHandle, NULL); pthread_condattr_init(&condattr);
pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC);
memset(&(PRIVATE->nativeHandle), 0, sizeof(PRIVATE->nativeHandle));
pthread_cond_init(&PRIVATE->nativeHandle, &condattr);
#endif #endif
} }
@@ -84,23 +86,38 @@ void PIConditionVariable::wait(PIMutex& lk, const std::function<bool()>& 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 PIConditionVariable::waitFor(PIMutex &lk, int timeoutMs) {
bool isNotTimeout; bool isNotTimeout;
#ifdef WINDOWS #ifdef WINDOWS
isNotTimeout = SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), timeoutMs) != 0; isNotTimeout = SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), timeoutMs) != 0;
#else #else
timespec abstime = {.tv_sec = timeoutMs / 1000, .tv_nsec = timeoutMs % 1000 * 1000000}; timespec expire_ts;
isNotTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &abstime) == 0; 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 #endif
if (PRIVATE->isDestroying) return false; if (PRIVATE->isDestroying) return false;
return isNotTimeout; return isNotTimeout;
} }
bool PIConditionVariable::waitFor(PIMutex& lk, int timeoutMs, const std::function<bool()> &condition) { bool PIConditionVariable::waitFor(PIMutex& lk, int timeoutMs, const std::function<bool()> &condition) {
bool isCondition; bool isCondition;
#ifdef WINDOWS
PITimeMeasurer measurer; PITimeMeasurer measurer;
#else
timespec expire_ts;
clock_gettime(CLOCK_MONOTONIC, &expire_ts);
timespec_add_ms(&expire_ts, timeoutMs);
#endif
while (true) { while (true) {
isCondition = condition(); isCondition = condition();
if (isCondition) break; if (isCondition) break;
@@ -110,9 +127,7 @@ bool PIConditionVariable::waitFor(PIMutex& lk, int timeoutMs, const std::functio
(PCRITICAL_SECTION)lk.handle(), (PCRITICAL_SECTION)lk.handle(),
timeoutMs - (int)measurer.elapsed_m()) == 0; timeoutMs - (int)measurer.elapsed_m()) == 0;
#else #else
int timeoutCurr = timeoutMs - (int)measurer.elapsed_m(); bool isTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &expire_ts) != 0;
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;
#endif #endif
if (isTimeout) return false; if (isTimeout) return false;
if (PRIVATE->isDestroying) return false; if (PRIVATE->isDestroying) return false;

View File

@@ -14,9 +14,7 @@ public:
void wait(PIMutex& lk, const std::function<bool()>& condition) override { void wait(PIMutex& lk, const std::function<bool()>& condition) override {
isWaitCalled = true; isWaitCalled = true;
lk.lock();
isTrueCondition = condition(); isTrueCondition = condition();
lk.unlock();
} }
bool waitFor(PIMutex& lk, int timeoutMs) override { bool waitFor(PIMutex& lk, int timeoutMs) override {
@@ -27,10 +25,8 @@ public:
bool waitFor(PIMutex& lk, int timeoutMs, const std::function<bool()>& condition) override { bool waitFor(PIMutex& lk, int timeoutMs, const std::function<bool()>& condition) override {
isWaitForCalled = true; isWaitForCalled = true;
lk.lock();
isTrueCondition = condition(); isTrueCondition = condition();
timeout = timeoutMs; timeout = timeoutMs;
lk.unlock();
return isTrueCondition; return isTrueCondition;
} }
}; };