#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(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(milliseconds/1000.0)*freq.QuadPart; return ts; } TimeSpan from_s(double seconds) { TimeSpan ts; ts.QuadPart = static_cast(seconds)*freq.QuadPart; return ts; } TimeSpan from_min(double minutes) { TimeSpan ts; ts.QuadPart = static_cast(minutes*60.0)*freq.QuadPart; return ts; } TimeSpan from_hours(double hours) { TimeSpan ts; ts.QuadPart = static_cast(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(sp.QuadPart*1000)/static_cast(freq.QuadPart); } double to_s(TimeSpan &sp) { return static_cast(sp.QuadPart)/static_cast(freq.QuadPart); } double to_min(TimeSpan &sp) { return static_cast(sp.QuadPart)/static_cast(freq.QuadPart*60); } double to_hours(TimeSpan &sp) { return static_cast(sp.QuadPart)/static_cast(freq.QuadPart*60*60); } #endif } // namespace sync //