#include "runtime.h" #include "threading.h" #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include struct vy_mutex_s { HANDLE handle; ptrdiff_t next_reusable; }; #define MAX_MUTEX 1024 static vy_mutex _mutex[MAX_MUTEX]; static ptrdiff_t _first_reusable = MAX_MUTEX; static ptrdiff_t _next = 0; VY_DLLEXPORT vy_mutex *vyCreateMutex(void) { if (_first_reusable < MAX_MUTEX) { vy_mutex *mtx = &_mutex[_first_reusable]; _first_reusable = mtx->next_reusable; return mtx; } else if (_next < MAX_MUTEX) { vy_mutex *mtx = &_mutex[_next]; mtx->handle = CreateMutexW(NULL, FALSE, NULL); if (!mtx->handle) { vyLog("core", "Mutex creation failed: %u", GetLastError()); return NULL; } mtx->next_reusable = MAX_MUTEX; ++_next; return mtx; } vyReportError("core", "Ran out of mutex objects"); return NULL; } VY_DLLEXPORT void vyDestroyMutex(vy_mutex *mutex) { ptrdiff_t index = mutex - &_mutex[0]; mutex->next_reusable = _first_reusable; _first_reusable = index; } VY_DLLEXPORT bool vyLockMutex(vy_mutex *mutex) { return WaitForSingleObject(mutex->handle, INFINITE) == WAIT_OBJECT_0; } v VY_DLLEXPORT bool vyUnlockMutex(vy_mutex *mutex) { return ReleaseMutex(mutex->handle) != 0; } #elif defined(__linux__) #include struct vy_mutex_s { pthread_mutex_t handle; ptrdiff_t next_reusable; }; #define MAX_MUTEX 1024 static vy_mutex _mutex[MAX_MUTEX]; static ptrdiff_t _first_reusable = MAX_MUTEX; static ptrdiff_t _next = 0; static pthread_mutex_t _guard = PTHREAD_MUTEX_INITIALIZER; VY_DLLEXPORT vy_mutex *vyCreateMutex(void) { pthread_mutex_lock(&_guard); if (_first_reusable < MAX_MUTEX) { vy_mutex *mtx = &_mutex[_first_reusable]; _first_reusable = mtx->next_reusable; pthread_mutex_unlock(&_guard); return mtx; } else if (_next < MAX_MUTEX) { vy_mutex *mtx = &_mutex[_next]; if (pthread_mutex_init(&mtx->handle, NULL) != 0) { vyLog("core", "Mutex creation failed"); pthread_mutex_unlock(&_guard); return NULL; } mtx->next_reusable = MAX_MUTEX; ++_next; pthread_mutex_unlock(&_guard); return mtx; } vyReportError("core", "Ran out of mutex objects"); pthread_mutex_unlock(&_guard); return NULL; } VY_DLLEXPORT void vyDestroyMutex(vy_mutex *mutex) { ptrdiff_t index = mutex - &_mutex[0]; pthread_mutex_lock(&_guard); mutex->next_reusable = _first_reusable; _first_reusable = index; pthread_mutex_unlock(&_guard); } VY_DLLEXPORT bool vyLockMutex(vy_mutex *mutex) { return pthread_mutex_lock(&mutex->handle) == 0; } VY_DLLEXPORT bool vyUnlockMutex(vy_mutex *mutex) { return pthread_mutex_unlock(&mutex->handle) == 0; } #endif