Files
CgeThread/posix/Semaphore.c

224 lines
5.0 KiB
C
Raw Normal View History

2026-08-09 12:55:16 +03:00
#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