#include "PlatformThreads.h" #include "Platform.h" struct thread_context { ThreadEntry entry; void* context; }; #ifdef LC_WINDOWS DWORD WINAPI ThreadProc(LPVOID lpParameter) { struct thread_context *ctx = (struct thread_context *)lpParameter; ctx->entry(ctx->context); free(ctx); return 0; } #else void* ThreadProc(void* context) { struct thread_context *ctx = (struct thread_context *)context; ctx->entry(ctx->context); free(ctx); return NULL; } #endif void PltSleepMs(int ms) { #ifdef LC_WINDOWS Sleep(ms); #else long usecs = (long)ms * 1000; usleep(usecs); #endif } int PltCreateMutex(PLT_MUTEX *mutex) { #if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE) *mutex = CreateMutexEx(NULL, NULL, 0, 0); if (!*mutex) { return -1; } return 0; #else return pthread_mutex_init(mutex, NULL); #endif } void PltDeleteMutex(PLT_MUTEX *mutex) { #if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE) CloseHandle(*mutex); #else pthread_mutex_destroy(mutex); #endif } void PltLockMutex(PLT_MUTEX *mutex) { #if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE) WaitForSingleObjectEx(*mutex, INFINITE, FALSE); #else pthread_mutex_lock(mutex); #endif } void PltUnlockMutex(PLT_MUTEX *mutex) { #if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE) ReleaseMutex(*mutex); #else pthread_mutex_unlock(mutex); #endif } void PltJoinThread(PLT_THREAD *thread) { #if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE) WaitForSingleObjectEx(*thread, INFINITE, FALSE); #else pthread_join(*thread, NULL); #endif } void PltCloseThread(PLT_THREAD *thread) { #if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE) CloseHandle(*thread); #else #endif } void PltInterruptThread(PLT_THREAD *thread) { #if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE) CloseHandle(*thread); #else pthread_cancel(*thread); #endif } int PltCreateThread(ThreadEntry entry, void* context, PLT_THREAD *thread) { struct thread_context *ctx; int err; ctx = (struct thread_context *)malloc(sizeof(*ctx)); if (ctx == NULL) { return -1; } ctx->entry = entry; ctx->context = context; #ifdef _WIN32 { HANDLE hThread = CreateThread(NULL, 0, ThreadProc, ctx, 0, NULL); if (hThread == NULL) { free(ctx); return -1; } else { CloseHandle(hThread); err = 0; } } #else { err = pthread_create(thread, NULL, ThreadProc, ctx); if (err != 0) { free(ctx); } } #endif return err; } int PltCreateEvent(PLT_EVENT *event) { #if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE) *event = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); if (!*event) { return -1; } return 0; #else pthread_mutex_init(&event->mutex, NULL); pthread_cond_init(&event->cond, NULL); event->signalled = 0; return 0; #endif } void PltCloseEvent(PLT_EVENT *event) { #ifdef _WIN32 CloseHandle(*event); #else pthread_mutex_destroy(&event->mutex); pthread_cond_destroy(&event->cond); #endif } void PltSetEvent(PLT_EVENT *event) { #ifdef _WIN32 SetEvent(*event); #else event->signalled = 1; pthread_cond_broadcast(&event->cond); #endif } void PltClearEvent(PLT_EVENT *event) { #ifdef _WIN32 ResetEvent(*event); #else event->signalled = 0; #endif } int PltWaitForEvent(PLT_EVENT *event) { #ifdef _WIN32 DWORD error = WaitForSingleObjectEx(*event, INFINITE, FALSE); if (error == STATUS_WAIT_0) { return PLT_WAIT_SUCCESS; } else if (error == WAIT_IO_COMPLETION) { return PLT_WAIT_INTERRUPTED; } else { LC_ASSERT(0); return -1; } #else pthread_mutex_lock(&event->mutex); while (!event->signalled) { pthread_cond_wait(&event->cond, &event->mutex); } pthread_mutex_unlock(&event->mutex); #endif }