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
|
#include "stdafx.h"
#include "Semaphore.h"
#ifdef WINDOWS
Semaphore::Semaphore(long count) {
semaphore = CreateSemaphore(NULL, count, 0x7FFFFFFF, NULL);
}
Semaphore::~Semaphore() {
CloseHandle(semaphore);
}
void Semaphore::up() {
ReleaseSemaphore(semaphore, 1, NULL);
}
void Semaphore::down() {
WaitForSingleObject(semaphore, INFINITE);
}
bool Semaphore::down(nat msTimeout) {
DWORD result = WaitForSingleObject(semaphore, msTimeout);
return result != WAIT_TIMEOUT;
}
#endif
#ifdef POSIX
Semaphore::Semaphore(long count) {
sem_init(&semaphore, 0, count);
}
Semaphore::~Semaphore() {
sem_destroy(&semaphore);
}
void Semaphore::up() {
sem_post(&semaphore);
}
void Semaphore::down() {
while (sem_wait(&semaphore) != 0) {
// We failed for some reason, probably a signal from the MPS.
if (errno != EINTR) {
perror("Waiting for a semaphore");
std::terminate();
}
}
}
static void fillTimespec(struct timespec *out, nat ms) {
clock_gettime(CLOCK_MONOTONIC, out);
// Increase with 'ms'...
const int64 maxNs = 1000LL * 1000LL * 1000LL;
int64 ns = ms * 1000LL * 1000LL;
ns += out->tv_nsec;
out->tv_sec += ns / maxNs;
out->tv_nsec = ns % maxNs;
}
bool Semaphore::down(nat msTimeout) {
struct timespec time = {0, 0};
fillTimespec(&time, msTimeout);
while (sem_timedwait(&semaphore, &time) != 0) {
// Failed for some reason...
switch (errno) {
case EINTR:
// Just a signal from the MPS. Retry!
// TODO: Adjust the time!
break;
case ETIMEDOUT:
// We timed out. That means we're done and should abort!
return false;
default:
perror("Waiting for a semaphore with a timeout");
std::terminate();
}
}
// If we get here, we managed to acquire the semaphore!
return true;
}
#endif
|