version 1.22.0
source tree changed detached PIConsole and PIScreen* in "pip_console" library
This commit is contained in:
142
lib/concurrent/piconditionvar.cpp
Normal file
142
lib/concurrent/piconditionvar.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 <windef.h>
|
||||
#include <winbase.h>
|
||||
#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<bool()>& 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<bool()> &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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user