diff options
Diffstat (limited to 'src/itc.c')
-rw-r--r-- | src/itc.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/src/itc.c b/src/itc.c new file mode 100644 index 0000000..6171d4e --- /dev/null +++ b/src/itc.c @@ -0,0 +1,104 @@ +#include "itc.h" +#include "utils.h" + +#include <semaphore.h> +#include <stdlib.h> +#include <sys/time.h> + +struct itc { + int nslots; + void **slots; + int inputidx; + int outputidx; + sem_t emptied; + sem_t occupied; +}; + +itc *itc_alloc(int nslots) +{ + itc *ctx; + + if (nslots <= 0) { + return NULL; + } + + ctx = calloc(1, sizeof(*ctx)); + ctx->nslots = nslots; + ctx->slots = calloc(nslots, sizeof(*ctx->slots)); + sem_init(&ctx->emptied, 0, nslots); + sem_init(&ctx->occupied, 0, 0); + + return ctx; +} + +void itc_free(itc **ctx, itc_free_element free_element) +{ + if (ctx == NULL || *ctx == NULL) { + return; + } + + itc_drop(*ctx, free_element); + + sem_destroy(&(*ctx)->emptied); + sem_destroy(&(*ctx)->occupied); + free((*ctx)->slots); + free(*ctx); + *ctx = NULL; +} + +void *itc_retrive(itc *ctx, int timeout_ms) +{ + struct timespec ts; + void *element; + + if (ctx == NULL) { + return NULL; + } + + timespec_add_ms(gettimespec(&ts), timeout_ms); + + if (sem_timedwait(&ctx->occupied, &ts)) { + return NULL; + } + element = ctx->slots[ctx->outputidx]; + ctx->outputidx = (ctx->outputidx + 1) % ctx->nslots; + sem_post(&ctx->emptied); + + return element; +} + +int itc_inject(itc *ctx, int timeout_ms, void *element) +{ + struct timespec ts; + + if (ctx == NULL) { + return -1; + } + + timespec_add_ms(gettimespec(&ts), timeout_ms); + + if (sem_timedwait(&ctx->emptied, &ts)) { + return -1; + } + ctx->slots[ctx->inputidx] = element; + ctx->inputidx = (ctx->inputidx + 1) % ctx->nslots; + sem_post(&ctx->occupied); + + return 0; +} + +void itc_drop(itc *ctx, itc_free_element free_element) +{ + void *element; + + if (ctx == NULL) { + return; + } + + while ((element = itc_retrive(ctx, 0)) != NULL) { + if (free_element != NULL) { + free_element(element); + } + } +} + |