This commit is contained in:
223
posix/Semaphore.c
Normal file
223
posix/Semaphore.c
Normal file
@@ -0,0 +1,223 @@
|
||||
#include "Internal.h"
|
||||
#include "Timespec.h"
|
||||
#include "Codemap.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#if (_POSIX_SEMAPHORES >= 200112L)
|
||||
CgeSemaphore *CgeSemaphoreNew(int value, int *result) {
|
||||
CgeSemaphore *semaphore;
|
||||
int code = CGE_THREAD_EOK;
|
||||
|
||||
semaphore = malloc(sizeof(CgeSemaphore));
|
||||
if (semaphore && sem_init(&semaphore->handle, 0, value)) {
|
||||
code = errorToErrorCode(errno);
|
||||
free(semaphore);
|
||||
semaphore = NULL;
|
||||
} else if (!semaphore) {
|
||||
code = CGE_THREAD_EOOM;
|
||||
}
|
||||
|
||||
if (result)
|
||||
*result = code;
|
||||
|
||||
return semaphore;
|
||||
}
|
||||
|
||||
void CgeSemaphoreFree(CgeSemaphore *semaphore) {
|
||||
if (!semaphore)
|
||||
return;
|
||||
|
||||
sem_destroy(&semaphore->handle);
|
||||
free(semaphore);
|
||||
}
|
||||
|
||||
|
||||
int CgeSemaphorePost(CgeSemaphore *semaphore, int *result) {
|
||||
int code = CGE_THREAD_EOK;
|
||||
|
||||
if (sem_post(&semaphore->handle))
|
||||
code = errorToErrorCode(errno);
|
||||
|
||||
if (result)
|
||||
*result = code;
|
||||
|
||||
return code == CGE_THREAD_EOK;
|
||||
}
|
||||
|
||||
|
||||
int CgeSemaphoreWait(CgeSemaphore *semaphore, int *result) {
|
||||
int code = CGE_THREAD_EOK;
|
||||
|
||||
if (sem_wait(&semaphore->handle))
|
||||
code = errorToErrorCode(errno);
|
||||
|
||||
if (result)
|
||||
*result = code;
|
||||
|
||||
return code == CGE_THREAD_EOK;
|
||||
}
|
||||
|
||||
|
||||
int CgeSemaphoreTryWait(CgeSemaphore *semaphore, int *result) {
|
||||
int code = CGE_THREAD_EOK;
|
||||
|
||||
if (sem_trywait(&semaphore->handle))
|
||||
code = errorToErrorCode(errno);
|
||||
|
||||
if (result)
|
||||
*result = code;
|
||||
|
||||
return code == CGE_THREAD_EOK;
|
||||
}
|
||||
|
||||
|
||||
int CgeSemaphoreWaitFor(CgeSemaphore *semaphore, uint32_t timeout, int *result) {
|
||||
struct timespec ts;
|
||||
int code = CGE_THREAD_EOK;
|
||||
|
||||
if (!convertToTimespec(&ts, timeout)) {
|
||||
if (result)
|
||||
*result = CGE_THREAD_EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sem_timedwait(&semaphore->handle, &ts))
|
||||
code = errorToErrorCode(errno);
|
||||
|
||||
if (result)
|
||||
*result = code;
|
||||
|
||||
return code == CGE_THREAD_EOK;
|
||||
}
|
||||
#else
|
||||
CgeSemaphore *CgeSemaphoreNew(int value, int *result) {
|
||||
CgeSemaphore *semaphore;
|
||||
int code = CGE_THREAD_EOOM;
|
||||
|
||||
if (semaphore = malloc(sizeof(*semaphore))) {
|
||||
semaphore->count = value;
|
||||
semaphore->waiters = 0;
|
||||
|
||||
if ((code = errorToErrorCode(pthread_mutex_init(&semaphore->mutex, NULL)))) {
|
||||
free(semaphore);
|
||||
if (result)
|
||||
*result = code;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((code = errorToErrorCode(pthread_cond_init(&semaphore->condition, NULL)))) {
|
||||
pthread_mutex_destroy(&semaphore->mutex);
|
||||
free(semaphore);
|
||||
if (result)
|
||||
*result = code;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
*result = code;
|
||||
|
||||
return semaphore;
|
||||
}
|
||||
|
||||
void CgeSemaphoreFree(CgeSemaphore *semaphore) {
|
||||
if (!semaphore)
|
||||
return;
|
||||
pthread_cond_destroy(&semaphore->condition);
|
||||
pthread_mutex_destroy(&semaphore->mutex);
|
||||
free(semaphore);
|
||||
}
|
||||
|
||||
int CgeSemaphorePost(CgeSemaphore *semaphore, int *result) {
|
||||
int code;
|
||||
|
||||
if ((code = errorToErrorCode(pthread_mutex_lock(&semaphore->mutex)))) {
|
||||
if (result)
|
||||
*result = code;
|
||||
return 0;
|
||||
}
|
||||
|
||||
semaphore->count++;
|
||||
if (semaphore->waiters && (code = errorToErrorCode(pthread_cond_signal(&semaphore->condition)))) {
|
||||
if (result)
|
||||
*result = code;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&semaphore->mutex);
|
||||
return code == CGE_THREAD_EOK;
|
||||
}
|
||||
|
||||
int CgeSemaphoreWait(CgeSemaphore *semaphore, int *result) {
|
||||
int code;
|
||||
|
||||
if ((code = pthread_mutex_lock(&semaphore->mutex))) {
|
||||
if (result)
|
||||
*result = code;
|
||||
return 0;
|
||||
}
|
||||
|
||||
semaphore->waiters++;
|
||||
while (!semaphore->count) {
|
||||
if ((code = errorToErrorCode(pthread_cond_wait(&semaphore->condition, &semaphore->mutex))))
|
||||
break;
|
||||
}
|
||||
semaphore->waiters--;
|
||||
semaphore->count--;
|
||||
pthread_mutex_unlock(&semaphore->mutex);
|
||||
|
||||
return code == CGE_THREAD_EOK;
|
||||
}
|
||||
|
||||
|
||||
int CgeSemaphoreTryWait(CgeSemaphore *semaphore, int *result) {
|
||||
int code;
|
||||
|
||||
if ((code = errorToErrorCode(pthread_mutex_lock(&semaphore->mutex)))) {
|
||||
if (result)
|
||||
*result = code;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!semaphore->count)
|
||||
code = CGE_THREAD_EBUSY;
|
||||
else
|
||||
semaphore->count--;
|
||||
|
||||
pthread_mutex_unlock(&semaphore->mutex);
|
||||
return code == CGE_THREAD_EOK;
|
||||
}
|
||||
|
||||
|
||||
int CgeSemaphoreWaitFor(CgeSemaphore *semaphore,
|
||||
uint32_t timeout, int *result) {
|
||||
struct timespec ts;
|
||||
int code;
|
||||
|
||||
if (!convertToTimespec(&ts, timeout)) {
|
||||
if (result)
|
||||
*result = CGE_THREAD_EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((code = errorToErrorCode(pthread_mutex_lock(&semaphore->mutex)))) {
|
||||
if (result)
|
||||
*result = code;
|
||||
return 0;
|
||||
}
|
||||
|
||||
semaphore->waiters++;
|
||||
while (!semaphore->count && code == CGE_THREAD_EOK) {
|
||||
code = errorToErrorCode(pthread_cond_timedwait(&semaphore->condition, &semaphore->mutex, &ts));
|
||||
}
|
||||
semaphore->waiters--;
|
||||
|
||||
if (code == CGE_THREAD_EOK)
|
||||
semaphore->count--;
|
||||
pthread_mutex_unlock(&semaphore->mutex);
|
||||
|
||||
if (result)
|
||||
*result = code;
|
||||
|
||||
return code == CGE_THREAD_EOK;
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user