Fix waitFor timeout behaviour
This commit is contained in:
@@ -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;
|
|
||||||
|
pthread_condattr_t condattr;
|
||||||
|
pthread_condattr_init(&condattr);
|
||||||
|
pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC);
|
||||||
memset(&(PRIVATE->nativeHandle), 0, sizeof(PRIVATE->nativeHandle));
|
memset(&(PRIVATE->nativeHandle), 0, sizeof(PRIVATE->nativeHandle));
|
||||||
pthread_cond_init(&PRIVATE->nativeHandle, NULL);
|
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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user