#include "piplatform.h" #include "piconditionvar.h" #include "pithread.h" #include "pitime.h" #ifdef WINDOWS #undef _WIN32_WINNT #define _WIN32_WINNT 0x0600 #include "synchapi.h" #include #include #endif PRIVATE_DEFINITION_START(PIConditionVariable) #ifdef WINDOWS CONDITION_VARIABLE nativeHandle; #else pthread_cond_t nativeHandle; PIConditionLock* currentLock; #endif bool isDestroying; PRIVATE_DEFINITION_END(PIConditionVariable) PIConditionVariable::PIConditionVariable() { #ifdef WINDOWS InitializeConditionVariable(&PRIVATE->nativeHandle); #else PRIVATE->isDestroying = false; PRIVATE->currentLock = nullptr; memset(&(PRIVATE->nativeHandle), 0, sizeof(PRIVATE->nativeHandle)); pthread_cond_init(&PRIVATE->nativeHandle, NULL); #endif } PIConditionVariable::~PIConditionVariable() { #ifdef WINDOWS #else pthread_cond_destroy(&PRIVATE->nativeHandle); #endif } void PIConditionVariable::wait(PIConditionLock& lk) { #ifdef WINDOWS SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), INFINITE); #else pthread_cond_wait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle()); #endif } void PIConditionVariable::wait(PIConditionLock& lk, const std::function& condition) { bool isCondition; while (true) { isCondition = condition(); if (isCondition) break; #ifdef WINDOWS SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), INFINITE); #else pthread_cond_wait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle()); #endif if (PRIVATE->isDestroying) return; } } bool PIConditionVariable::waitFor(PIConditionLock &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 * 1000}; isNotTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &abstime) == 0; #endif if (PRIVATE->isDestroying) return false; return isNotTimeout; } bool PIConditionVariable::waitFor(PIConditionLock& lk, int timeoutMs, const std::function &condition) { bool isCondition; PITimeMeasurer measurer; while (true) { isCondition = condition(); if (isCondition) break; #ifdef WINDOWS WINBOOL isTimeout = SleepConditionVariableCS( &PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), timeoutMs - (int)measurer.elapsed_m()); if (isTimeout == 0) return false; #else int timeoutCurr = timeoutMs - (int)measurer.elapsed_m(); timespec abstime = {.tv_sec = timeoutCurr / 1000, .tv_nsec = timeoutCurr * 1000 * 1000}; bool isTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &abstime) == 0; if (isTimeout) return false; #endif if (PRIVATE->isDestroying) return false; } return true; } void PIConditionVariable::notifyOne() { #ifdef WINDOWS WakeConditionVariable(&PRIVATE->nativeHandle); #else pthread_cond_signal(&PRIVATE->nativeHandle); #endif } void PIConditionVariable::notifyAll() { #ifdef WINDOWS WakeAllConditionVariable(&PRIVATE->nativeHandle); #else pthread_cond_broadcast(&PRIVATE->nativeHandle); #endif }