git-svn-id: svn://db.shs.com.ru/pip@868 12ceb7fc-bf1f-11e4-8940-5bc7170c53b5
129 lines
3.8 KiB
C++
129 lines
3.8 KiB
C++
//
|
|
// Created by fomenko on 20.09.2019.
|
|
//
|
|
|
|
#include "piplatform.h"
|
|
|
|
#ifdef WINDOWS
|
|
#define _WIN32_WINNT 0x0600
|
|
#include "synchapi.h"
|
|
#include <windef.h>
|
|
#include <winbase.h>
|
|
#endif
|
|
|
|
#include "piconditionvar.h"
|
|
#include "pithread.h"
|
|
#include "pitime.h"
|
|
|
|
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
|
|
}
|
|
|
|
void StdFunctionThreadFuncAdapter::threadFuncStdFunctionAdapter(void *it) {
|
|
auto consumer = (StdFunctionThreadFuncAdapter*)it;
|
|
consumer->fun();
|
|
}
|
|
|
|
void StdFunctionThreadFuncAdapter::registerToInvoke(PIThread *thread) {
|
|
thread->setData(data());
|
|
thread->setSlot((ThreadFunc) threadFunc());
|
|
}
|