1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
|
#include "stdafx.h"
#include "Condition.h"
namespace os {
#ifdef WINDOWS
Condition::Condition() : signaled(0) {
sema = CreateSemaphore(NULL, 0, 1, NULL);
}
Condition::~Condition() {
CloseHandle(sema);
}
void Condition::signal() {
// If we're the first one to signal, alter the semaphore.
if (atomicCAS(signaled, 0, 1) == 0)
ReleaseSemaphore(sema, 1, NULL);
}
void Condition::wait() {
// Wait for someone to signal, and then reset the signaled state for next time.
WaitForSingleObject(sema, INFINITE);
atomicCAS(signaled, 1, 0);
}
bool Condition::wait(nat msTimeout) {
DWORD result = WaitForSingleObject(sema, msTimeout);
if (result == WAIT_OBJECT_0) {
atomicCAS(signaled, 1, 0);
return true;
} else {
return false;
}
}
#endif
#ifdef POSIX
Condition::Condition() : signaled(0) {
pthread_condattr_t attr;
pthread_condattr_init(&attr);
pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
pthread_cond_init(&cond, &attr);
pthread_condattr_destroy(&attr);
pthread_mutex_init(&mutex, null);
}
Condition::~Condition() {
pthread_cond_destroy(&cond);
}
void Condition::signal() {
if (atomicCAS(signaled, 0, 1) == 0)
pthread_cond_signal(&cond);
}
void Condition::wait() {
pthread_mutex_lock(&mutex);
if (atomicCAS(signaled, 1, 0) == 0)
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
}
static long ns(long ms) {
return ms * 1000000;
}
static struct timespec timeMs(nat ms) {
struct timespec time = {0, 0};
clock_gettime(CLOCK_MONOTONIC, &time);
nat s = ms / 1000;
ms = ms % 1000;
time.tv_sec += s;
time.tv_nsec += ns(ms);
while (time.tv_nsec >= ns(1000)) {
time.tv_nsec -= ns(1000);
time.tv_sec += 1;
}
return time;
}
bool Condition::wait(nat msTimeout) {
struct timespec time = timeMs(msTimeout);;
int r = 0;
pthread_mutex_lock(&mutex);
if (atomicCAS(signaled, 1, 0) == 0)
r = pthread_cond_timedwait(&cond, &mutex, &time);
pthread_mutex_unlock(&mutex);
if (r == 0)
return true;
else
return errno != ETIMEDOUT;
}
#endif
}
|