/* PIP - Platform Independent Primitives Stephan Fomenko This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "piconditionvar.h" #include "pithread.h" #include "pitime.h" #ifdef WINDOWS # undef _WIN32_WINNT # define _WIN32_WINNT 0x0600 # include # include # include #endif PRIVATE_DEFINITION_START(PIConditionVariable) #ifdef WINDOWS CONDITION_VARIABLE nativeHandle; #else pthread_cond_t nativeHandle; #endif PRIVATE_DEFINITION_END(PIConditionVariable) PIConditionVariable::PIConditionVariable() { #ifdef WINDOWS InitializeConditionVariable(&PRIVATE->nativeHandle); #else pthread_condattr_t condattr; pthread_condattr_init(&condattr); # ifndef MAC_OS pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC); # endif memset(&(PRIVATE->nativeHandle), 0, sizeof(PRIVATE->nativeHandle)); pthread_cond_init(&PRIVATE->nativeHandle, &condattr); #endif } PIConditionVariable::~PIConditionVariable() { #ifdef WINDOWS #else pthread_cond_destroy(&PRIVATE->nativeHandle); #endif } void PIConditionVariable::wait(PIMutex& 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(PIMutex& 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 } } bool PIConditionVariable::waitFor(PIMutex &lk, int timeoutMs) { bool isNotTimeout; #ifdef WINDOWS isNotTimeout = SleepConditionVariableCS(&PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), timeoutMs) != 0; #else timespec expire_ts; PISystemTime st = PISystemTime::current(true); st.addMilliseconds(timeoutMs); st.toTimespec(&expire_ts); isNotTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &expire_ts) == 0; #endif return isNotTimeout; } bool PIConditionVariable::waitFor(PIMutex& lk, int timeoutMs, const std::function &condition) { bool isCondition; #ifdef WINDOWS PITimeMeasurer measurer; #else timespec expire_ts; PISystemTime st = PISystemTime::current(true); st.addMilliseconds(timeoutMs); st.toTimespec(&expire_ts); #endif while (true) { isCondition = condition(); if (isCondition) break; #ifdef WINDOWS bool isTimeout = SleepConditionVariableCS( &PRIVATE->nativeHandle, (PCRITICAL_SECTION)lk.handle(), timeoutMs - (int)measurer.elapsed_m()) == 0; #else bool isTimeout = pthread_cond_timedwait(&PRIVATE->nativeHandle, (pthread_mutex_t*)lk.handle(), &expire_ts) != 0; #endif if (isTimeout) 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 }