Commit 13c7a038 authored by David Reid's avatar David Reid

Add custom semaphore implementation for POSIX platforms.

This is needing to be done manually because Apple has decided to
deprecate anonymous semaphores from semaphore.h which we're going to
need.
parent ebf0826b
...@@ -1569,7 +1569,6 @@ extern "C" { ...@@ -1569,7 +1569,6 @@ extern "C" {
/* We only use multi-threading with the device IO API, so no need to include these headers otherwise. */ /* We only use multi-threading with the device IO API, so no need to include these headers otherwise. */
#if !defined(MA_NO_DEVICE_IO) #if !defined(MA_NO_DEVICE_IO)
#include <pthread.h> /* Unfortunate #include, but needed for pthread_t, pthread_mutex_t and pthread_cond_t types. */ #include <pthread.h> /* Unfortunate #include, but needed for pthread_t, pthread_mutex_t and pthread_cond_t types. */
#include <semaphore.h>
#endif #endif
#ifdef __unix__ #ifdef __unix__
...@@ -3026,25 +3025,17 @@ typedef struct ...@@ -3026,25 +3025,17 @@ typedef struct
} ma_event; } ma_event;
#endif #endif
#if defined(MA_WIN32)
typedef ma_handle ma_semaphore;
#endif
#if defined(MA_POSIX)
typedef struct typedef struct
{ {
union int value;
{ pthread_mutex_t lock;
#ifdef MA_WIN32 pthread_cond_t cond;
struct
{
/*HANDLE*/ ma_handle hSemaphore;
} win32;
#endif
#ifdef MA_POSIX
struct
{
sem_t semaphore;
} posix;
#endif
int _unused;
};
} ma_semaphore; } ma_semaphore;
#endif
/* /*
...@@ -7767,8 +7758,8 @@ static ma_bool32 ma_event_signal__win32(ma_event* pEvent) ...@@ -7767,8 +7758,8 @@ static ma_bool32 ma_event_signal__win32(ma_event* pEvent)
static ma_result ma_semaphore_init__win32(int initialValue, ma_semaphore* pSemaphore) static ma_result ma_semaphore_init__win32(int initialValue, ma_semaphore* pSemaphore)
{ {
pSemaphore->win32.hSemaphore = CreateSemaphoreW(NULL, (LONG)initialValue, LONG_MAX, NULL); *pSemaphore = CreateSemaphoreW(NULL, (LONG)initialValue, LONG_MAX, NULL);
if (pSemaphore->win32.hSemaphore == NULL) { if (*pSemaphore == NULL) {
return ma_result_from_GetLastError(GetLastError()); return ma_result_from_GetLastError(GetLastError());
} }
...@@ -7777,17 +7768,17 @@ static ma_result ma_semaphore_init__win32(int initialValue, ma_semaphore* pSemap ...@@ -7777,17 +7768,17 @@ static ma_result ma_semaphore_init__win32(int initialValue, ma_semaphore* pSemap
static void ma_semaphore_uninit__win32(ma_semaphore* pSemaphore) static void ma_semaphore_uninit__win32(ma_semaphore* pSemaphore)
{ {
CloseHandle((HANDLE)pSemaphore->win32.hSemaphore); CloseHandle((HANDLE)*pSemaphore);
} }
static ma_bool32 ma_semaphore_wait__win32(ma_semaphore* pSemaphore) static ma_bool32 ma_semaphore_wait__win32(ma_semaphore* pSemaphore)
{ {
return WaitForSingleObject((HANDLE)pSemaphore->win32.hSemaphore, INFINITE) == WAIT_OBJECT_0; return WaitForSingleObject((HANDLE)*pSemaphore, INFINITE) == WAIT_OBJECT_0;
} }
static ma_bool32 ma_semaphore_release__win32(ma_semaphore* pSemaphore) static ma_bool32 ma_semaphore_release__win32(ma_semaphore* pSemaphore)
{ {
return ReleaseSemaphore((HANDLE)pSemaphore->win32.hSemaphore, 1, NULL) != 0; return ReleaseSemaphore((HANDLE)*pSemaphore, 1, NULL) != 0;
} }
#endif #endif
...@@ -7865,7 +7856,7 @@ static ma_result ma_thread_create__posix(ma_thread* pThread, ma_thread_priority ...@@ -7865,7 +7856,7 @@ static ma_result ma_thread_create__posix(ma_thread* pThread, ma_thread_priority
static void ma_thread_wait__posix(ma_thread* pThread) static void ma_thread_wait__posix(ma_thread* pThread)
{ {
pthread_join(pThread, NULL); pthread_join(*pThread, NULL);
} }
#if !defined(MA_EMSCRIPTEN) #if !defined(MA_EMSCRIPTEN)
...@@ -7971,33 +7962,72 @@ static ma_bool32 ma_event_signal__posix(ma_event* pEvent) ...@@ -7971,33 +7962,72 @@ static ma_bool32 ma_event_signal__posix(ma_event* pEvent)
static ma_result ma_semaphore_init__posix(int initialValue, ma_semaphore* pSemaphore) static ma_result ma_semaphore_init__posix(int initialValue, ma_semaphore* pSemaphore)
{ {
#if defined(MA_APPLE) int result;
/* Not yet implemented for Apple platforms since sem_init() is deprecated. Need to use a named semaphore via sem_open() instead. */
(void)initialValue; if (pSemaphore == NULL) {
(void)pSemaphore; return MA_INVALID_ARGS;
return MA_INVALID_OPERATION; }
#else
if (sem_init(&pSemaphore->posix.semaphore, 0, (unsigned int)initialValue) == 0) { pSemaphore->value = initialValue;
return ma_result_from_errno(errno);
result = pthread_mutex_init(&pSemaphore->lock, NULL);
if (result != 0) {
return ma_result_from_errno(result); /* Failed to create mutex. */
}
result = pthread_cond_init(&pSemaphore->cond, NULL);
if (result != 0) {
pthread_mutex_destroy(&pSemaphore->lock);
return ma_result_from_errno(result); /* Failed to create condition variable. */
} }
#endif
return MA_SUCCESS; return MA_SUCCESS;
} }
static void ma_semaphore_uninit__posix(ma_semaphore* pSemaphore) static void ma_semaphore_uninit__posix(ma_semaphore* pSemaphore)
{ {
sem_close(&pSemaphore->posix.semaphore); if (pSemaphore == NULL) {
return;
}
pthread_cond_destroy(&pSemaphore->cond);
pthread_mutex_destroy(&pSemaphore->lock);
} }
static ma_bool32 ma_semaphore_wait__posix(ma_semaphore* pSemaphore) static ma_bool32 ma_semaphore_wait__posix(ma_semaphore* pSemaphore)
{ {
return sem_wait(&pSemaphore->posix.semaphore) != -1; if (pSemaphore == NULL) {
return MA_FALSE;
}
pthread_mutex_lock(&pSemaphore->lock);
{
/* We need to wait on a condition variable before escaping. We can't return from this function until the semaphore has been signaled. */
while (pSemaphore->value == 0) {
pthread_cond_wait(&pSemaphore->cond, &pSemaphore->lock);
}
pSemaphore->value -= 1;
}
pthread_mutex_unlock(&pSemaphore->lock);
return MA_TRUE;
} }
static ma_bool32 ma_semaphore_release__posix(ma_semaphore* pSemaphore) static ma_bool32 ma_semaphore_release__posix(ma_semaphore* pSemaphore)
{ {
return sem_post(&pSemaphore->posix.semaphore) != -1; if (pSemaphore == NULL) {
return MA_FALSE;
}
pthread_mutex_lock(&pSemaphore->lock);
{
pSemaphore->value += 1;
pthread_cond_signal(&pSemaphore->cond);
}
pthread_mutex_unlock(&pSemaphore->lock);
return MA_TRUE;
} }
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment