Add ChiakiPredCond

This commit is contained in:
Florian Märkl 2019-06-14 10:31:30 +02:00
commit e1befb2e90
No known key found for this signature in database
GPG key ID: 125BC8A5A6A1E857
2 changed files with 138 additions and 11 deletions

View file

@ -25,6 +25,7 @@ extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
#include <pthread.h>
typedef struct chiaki_thread_t
@ -63,6 +64,23 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_cond_signal(ChiakiCond *cond);
CHIAKI_EXPORT ChiakiErrorCode chiaki_cond_broadcast(ChiakiCond *cond);
typedef struct chiaki_pred_cond_t
{
ChiakiCond cond;
ChiakiMutex mutex;
bool pred;
} ChiakiPredCond;
CHIAKI_EXPORT ChiakiErrorCode chiaki_pred_cond_init(ChiakiPredCond *cond);
CHIAKI_EXPORT ChiakiErrorCode chiaki_pred_cond_fini(ChiakiPredCond *cond);
CHIAKI_EXPORT ChiakiErrorCode chiaki_pred_cond_lock(ChiakiPredCond *cond);
CHIAKI_EXPORT ChiakiErrorCode chiaki_pred_cond_unlock(ChiakiPredCond *cond);
CHIAKI_EXPORT ChiakiErrorCode chiaki_pred_cond_wait(ChiakiPredCond *cond);
CHIAKI_EXPORT ChiakiErrorCode chiaki_pred_cond_timedwait(ChiakiPredCond *cond, uint64_t timeout_ms);
CHIAKI_EXPORT void chiaki_pred_cond_reset(ChiakiPredCond *cond);
CHIAKI_EXPORT ChiakiErrorCode chiaki_pred_cond_signal(ChiakiPredCond *cond);
CHIAKI_EXPORT ChiakiErrorCode chiaki_pred_cond_broadcast(ChiakiPredCond *cond);
#ifdef __cplusplus
}
#endif

View file

@ -124,18 +124,9 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_cond_wait(ChiakiCond *cond, ChiakiMutex *mu
return CHIAKI_ERR_SUCCESS;
}
CHIAKI_EXPORT ChiakiErrorCode chiaki_cond_timedwait(ChiakiCond *cond, ChiakiMutex *mutex, uint64_t timeout_ms)
static ChiakiErrorCode chiaki_cond_timedwait_abs(ChiakiCond *cond, ChiakiMutex *mutex, struct timespec *timeout)
{
struct timespec timeout;
clock_gettime(CLOCK_MONOTONIC, &timeout);
timeout.tv_sec += timeout_ms / 1000;
timeout.tv_nsec += (timeout_ms % 1000) * 1000000;
if(timeout.tv_nsec > 1000000000)
{
timeout.tv_sec += timeout.tv_nsec / 1000000000;
timeout.tv_nsec %= 1000000000;
}
int r = pthread_cond_timedwait(&cond->cond, &mutex->mutex, &timeout);
int r = pthread_cond_timedwait(&cond->cond, &mutex->mutex, timeout);
if(r != 0)
{
if(r == ETIMEDOUT)
@ -145,6 +136,25 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_cond_timedwait(ChiakiCond *cond, ChiakiMute
return CHIAKI_ERR_SUCCESS;
}
static void set_timeout(struct timespec *timeout, uint64_t ms_from_now)
{
clock_gettime(CLOCK_MONOTONIC, timeout);
timeout->tv_sec += ms_from_now / 1000;
timeout->tv_nsec += (ms_from_now % 1000) * 1000000;
if(timeout->tv_nsec > 1000000000)
{
timeout->tv_sec += timeout->tv_nsec / 1000000000;
timeout->tv_nsec %= 1000000000;
}
}
CHIAKI_EXPORT ChiakiErrorCode chiaki_cond_timedwait(ChiakiCond *cond, ChiakiMutex *mutex, uint64_t timeout_ms)
{
struct timespec timeout;
set_timeout(&timeout, timeout_ms);
return chiaki_cond_timedwait_abs(cond, mutex, &timeout);
}
CHIAKI_EXPORT ChiakiErrorCode chiaki_cond_signal(ChiakiCond *cond)
{
int r = pthread_cond_signal(&cond->cond);
@ -160,3 +170,102 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_cond_broadcast(ChiakiCond *cond)
return CHIAKI_ERR_UNKNOWN;
return CHIAKI_ERR_SUCCESS;
}
CHIAKI_EXPORT ChiakiErrorCode chiaki_pred_cond_init(ChiakiPredCond *cond)
{
cond->pred = false;
ChiakiErrorCode err = chiaki_mutex_init(&cond->mutex);
if(err != CHIAKI_ERR_SUCCESS)
return err;
err = chiaki_cond_init(&cond->cond);
if(err != CHIAKI_ERR_SUCCESS)
{
chiaki_mutex_fini(&cond->mutex);
return err;
}
return CHIAKI_ERR_SUCCESS;
}
CHIAKI_EXPORT ChiakiErrorCode chiaki_pred_cond_fini(ChiakiPredCond *cond)
{
ChiakiErrorCode err = chiaki_cond_fini(&cond->cond);
if(err != CHIAKI_ERR_SUCCESS)
return err;
err = chiaki_mutex_fini(&cond->mutex);
if(err != CHIAKI_ERR_SUCCESS)
return err;
return CHIAKI_ERR_SUCCESS;
}
CHIAKI_EXPORT ChiakiErrorCode chiaki_pred_cond_lock(ChiakiPredCond *cond)
{
return chiaki_mutex_lock(&cond->mutex);
}
CHIAKI_EXPORT ChiakiErrorCode chiaki_pred_cond_unlock(ChiakiPredCond *cond)
{
return chiaki_mutex_unlock(&cond->mutex);
}
CHIAKI_EXPORT ChiakiErrorCode chiaki_pred_cond_wait(ChiakiPredCond *cond)
{
while(!cond->pred)
{
ChiakiErrorCode err = chiaki_cond_wait(&cond->cond, &cond->mutex);
if(err != CHIAKI_ERR_SUCCESS)
return err;
}
return CHIAKI_ERR_SUCCESS;
}
CHIAKI_EXPORT ChiakiErrorCode chiaki_pred_cond_timedwait(ChiakiPredCond *cond, uint64_t timeout_ms)
{
struct timespec timeout;
set_timeout(&timeout, timeout_ms);
while(!cond->pred)
{
ChiakiErrorCode err = chiaki_cond_timedwait_abs(&cond->cond, &cond->mutex, &timeout);
if(err != CHIAKI_ERR_SUCCESS)
return err;
}
return CHIAKI_ERR_SUCCESS;
}
CHIAKI_EXPORT void chiaki_pred_cond_reset(ChiakiPredCond *cond)
{
cond->pred = false;
}
CHIAKI_EXPORT ChiakiErrorCode chiaki_pred_cond_signal(ChiakiPredCond *cond)
{
ChiakiErrorCode err = chiaki_mutex_lock(&cond->mutex);
if(err != CHIAKI_ERR_SUCCESS)
return err;
cond->pred = true;
err = chiaki_cond_signal(&cond->cond);
ChiakiErrorCode unlock_err = chiaki_mutex_unlock(&cond->mutex);
return err == CHIAKI_ERR_SUCCESS ? unlock_err : err;
}
CHIAKI_EXPORT ChiakiErrorCode chiaki_pred_cond_broadcast(ChiakiPredCond *cond)
{
ChiakiErrorCode err = chiaki_mutex_lock(&cond->mutex);
if(err != CHIAKI_ERR_SUCCESS)
return err;
cond->pred = true;
err = chiaki_cond_broadcast(&cond->cond);
ChiakiErrorCode unlock_err = chiaki_mutex_unlock(&cond->mutex);
return err == CHIAKI_ERR_SUCCESS ? unlock_err : err;
}