191 lines
4.0 KiB
C++
191 lines
4.0 KiB
C++
#pragma once
|
|
|
|
#ifdef _WIN32
|
|
#include "windows.h"
|
|
#endif
|
|
|
|
namespace sync {
|
|
|
|
#ifdef _WIN32
|
|
typedef CRITICAL_SECTION Mutex;
|
|
typedef CONDITION_VARIABLE ConditionVar;
|
|
typedef HANDLE Semaphore;
|
|
typedef HANDLE Thread;
|
|
typedef LARGE_INTEGER TimeSpan;
|
|
typedef DWORD (WINAPI *ThreadFunc)(_In_ LPVOID lpParameter);
|
|
typedef LPVOID ThreadArg;
|
|
|
|
const TimeSpan infinite_ts = { .QuadPart = LLONG_MAX };
|
|
|
|
LARGE_INTEGER _init_freq() {
|
|
LARGE_INTEGER freq;
|
|
QueryPerformanceFrequency(&freq);
|
|
return freq;
|
|
}
|
|
|
|
static LARGE_INTEGER freq = _init_freq();
|
|
#endif
|
|
|
|
Thread make_thread(ThreadFunc t, ThreadArg a);
|
|
void join(Thread t);
|
|
|
|
Mutex make_mutex();
|
|
void lock(Mutex &m);
|
|
bool trylock(Mutex &m);
|
|
void unlock(Mutex &m);
|
|
void dispose(Mutex &m);
|
|
|
|
ConditionVar make_condition_var();
|
|
void wait(ConditionVar &c, Mutex &m, TimeSpan ts);
|
|
void wake_one(ConditionVar &c);
|
|
void wake_all(ConditionVar &c);
|
|
void dispose(ConditionVar &c);
|
|
|
|
Semaphore make_semaphore(int initial, int max);
|
|
void wait(Semaphore &s);
|
|
void post(Semaphore &s);
|
|
void dispose(Semaphore &s);
|
|
|
|
TimeSpan from_ms(double milliseconds);
|
|
TimeSpan from_s(double seconds);
|
|
TimeSpan from_min(double minutes);
|
|
TimeSpan from_hours(double hours);
|
|
TimeSpan now();
|
|
TimeSpan operator-(const TimeSpan &a, const TimeSpan &b);
|
|
|
|
double to_ms(TimeSpan &sp);
|
|
double to_s(TimeSpan &sp);
|
|
double to_min(TimeSpan &sp);
|
|
double to_hours(TimeSpan &sp);
|
|
|
|
#ifdef _WIN32
|
|
|
|
Thread make_thread(ThreadFunc f, ThreadArg a) {
|
|
DWORD tid;
|
|
return CreateThread(NULL, 0, f, a, 0, &tid);
|
|
}
|
|
|
|
void join(Thread t) {
|
|
WaitForSingleObject(t, INFINITE);
|
|
}
|
|
|
|
Mutex make_mutex() {
|
|
Mutex m;
|
|
InitializeCriticalSection(&m);
|
|
return m;
|
|
}
|
|
|
|
void lock(Mutex &m) {
|
|
EnterCriticalSection(&m);
|
|
}
|
|
|
|
bool trylock(Mutex &m) {
|
|
return TryEnterCriticalSection(&m);
|
|
}
|
|
|
|
void unlock(Mutex &m) {
|
|
LeaveCriticalSection(&m);
|
|
}
|
|
|
|
void dispose(Mutex &m) {
|
|
DeleteCriticalSection(&m);
|
|
}
|
|
|
|
ConditionVar make_condition_var() {
|
|
ConditionVar c;
|
|
InitializeConditionVariable(&c);
|
|
return c;
|
|
}
|
|
|
|
void wait(ConditionVar &c, Mutex &m, TimeSpan ts) {
|
|
if (ts.QuadPart == infinite_ts.QuadPart) {
|
|
SleepConditionVariableCS(&c, &m, INFINITE);
|
|
} else {
|
|
SleepConditionVariableCS(&c, &m, static_cast<DWORD>(to_ms(ts)));
|
|
}
|
|
}
|
|
|
|
void wake_one(ConditionVar &c) {
|
|
WakeConditionVariable(&c);
|
|
}
|
|
|
|
void wake_all(ConditionVar &c) {
|
|
WakeAllConditionVariable(&c);
|
|
}
|
|
|
|
void dispose(ConditionVar &c) {
|
|
return; // Windows doesn't have a delete condition variable func
|
|
}
|
|
|
|
Semaphore make_semaphore(int initial, int max) {
|
|
return CreateSemaphoreA(NULL, (long)initial, (long)max, NULL);
|
|
}
|
|
|
|
void wait(Semaphore &s) {
|
|
WaitForSingleObject(s, INFINITE);
|
|
}
|
|
|
|
void post(Semaphore &s) {
|
|
ReleaseSemaphore(s, 1, NULL);
|
|
}
|
|
|
|
void dispose(Semaphore &s) {
|
|
CloseHandle(s);
|
|
}
|
|
|
|
TimeSpan from_ms(double milliseconds) {
|
|
TimeSpan ts;
|
|
ts.QuadPart = static_cast<LONGLONG>(milliseconds/1000.0)*freq.QuadPart;
|
|
return ts;
|
|
}
|
|
|
|
TimeSpan from_s(double seconds) {
|
|
TimeSpan ts;
|
|
ts.QuadPart = static_cast<LONGLONG>(seconds)*freq.QuadPart;
|
|
return ts;
|
|
}
|
|
|
|
TimeSpan from_min(double minutes) {
|
|
TimeSpan ts;
|
|
ts.QuadPart = static_cast<LONGLONG>(minutes*60.0)*freq.QuadPart;
|
|
return ts;
|
|
}
|
|
|
|
TimeSpan from_hours(double hours) {
|
|
TimeSpan ts;
|
|
ts.QuadPart = static_cast<LONGLONG>(hours*60.0*60.0)*freq.QuadPart;
|
|
return ts;
|
|
}
|
|
|
|
TimeSpan now() {
|
|
TimeSpan ts;
|
|
QueryPerformanceCounter(&ts);
|
|
return ts;
|
|
}
|
|
|
|
TimeSpan operator-(const TimeSpan &a, TimeSpan &b) {
|
|
TimeSpan ts;
|
|
ts.QuadPart = a.QuadPart - b.QuadPart;
|
|
return ts;
|
|
}
|
|
|
|
double to_ms(TimeSpan &sp) {
|
|
return static_cast<double>(sp.QuadPart*1000)/static_cast<double>(freq.QuadPart);
|
|
}
|
|
|
|
double to_s(TimeSpan &sp) {
|
|
return static_cast<double>(sp.QuadPart)/static_cast<double>(freq.QuadPart);
|
|
}
|
|
|
|
double to_min(TimeSpan &sp) {
|
|
return static_cast<double>(sp.QuadPart)/static_cast<double>(freq.QuadPart*60);
|
|
}
|
|
|
|
double to_hours(TimeSpan &sp) {
|
|
return static_cast<double>(sp.QuadPart)/static_cast<double>(freq.QuadPart*60*60);
|
|
}
|
|
|
|
#endif
|
|
|
|
} // namespace sync
|