diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-08-11 14:47:34 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-08-11 14:47:34 -0400 |
| commit | 2ecb5fe885042ca6c25ee0a3e3da070ddec9e07e (patch) | |
| tree | cdd7c7d1d51982d4074f76a1bccc522fbc8b5eee /builtins/channel.c | |
| parent | 3bf8ea8e12a2728bf63968ca7b42359b089e318b (diff) | |
Add channels and threads
Diffstat (limited to 'builtins/channel.c')
| -rw-r--r-- | builtins/channel.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/builtins/channel.c b/builtins/channel.c new file mode 100644 index 00000000..0b5f7411 --- /dev/null +++ b/builtins/channel.c @@ -0,0 +1,102 @@ +// Functions that operate on channels + +#include <ctype.h> +#include <err.h> +#include <gc.h> +#include <gc/cord.h> +#include <math.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> +#include <pthread.h> +#include <sys/param.h> + +#include "array.h" +#include "functions.h" +#include "halfsiphash.h" +#include "types.h" +#include "util.h" + +public channel_t *Channel$new(void) +{ + channel_t *channel = new(channel_t); + channel->items = (array_t){}; + channel->mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; + channel->cond = (pthread_cond_t)PTHREAD_COND_INITIALIZER; + return channel; +} + +public void Channel$push(channel_t *channel, const void *item, int64_t padded_item_size) +{ + (void)pthread_mutex_lock(&channel->mutex); + Array$insert(&channel->items, item, 0, padded_item_size); + (void)pthread_mutex_unlock(&channel->mutex); + (void)pthread_cond_signal(&channel->cond); +} + +public void Channel$push_all(channel_t *channel, array_t to_push, int64_t padded_item_size) +{ + (void)pthread_mutex_lock(&channel->mutex); + Array$insert_all(&channel->items, to_push, 0, padded_item_size); + (void)pthread_mutex_unlock(&channel->mutex); + (void)pthread_cond_signal(&channel->cond); +} + +public void Channel$pop(channel_t *channel, void *out, int64_t item_size, int64_t padded_item_size) +{ + (void)pthread_mutex_lock(&channel->mutex); + while (channel->items.length == 0) + pthread_cond_wait(&channel->cond, &channel->mutex); + memcpy(out, channel->items.data, item_size); + Array$remove(&channel->items, 1, 1, padded_item_size); + (void)pthread_mutex_unlock(&channel->mutex); +} + +public array_t Channel$view(channel_t *channel) +{ + (void)pthread_mutex_lock(&channel->mutex); + ARRAY_INCREF(channel->items); + array_t ret = channel->items; + (void)pthread_mutex_unlock(&channel->mutex); + return ret; +} + +public void Channel$clear(channel_t *channel) +{ + (void)pthread_mutex_lock(&channel->mutex); + Array$clear(&channel->items); + (void)pthread_mutex_unlock(&channel->mutex); +} + +public uint32_t Channel$hash(const channel_t **channel, const TypeInfo *type) +{ + (void)type; + uint32_t hash; + halfsiphash(*channel, sizeof(channel_t*), TOMO_HASH_KEY, (uint8_t*)&hash, sizeof(hash)); + return hash; +} + +public int32_t Channel$compare(const channel_t **x, const channel_t **y, const TypeInfo *type) +{ + (void)type; + return (*x > *y) - (*x < *y); +} + +bool Channel$equal(const channel_t **x, const channel_t **y, const TypeInfo *type) +{ + (void)type; + return (*x == *y); +} + +CORD Channel$as_text(const channel_t **channel, bool colorize, const TypeInfo *type) +{ + const TypeInfo *item_type = type->ChannelInfo.item; + if (!channel) { + CORD typename = generic_as_text(NULL, false, item_type); + return colorize ? CORD_asprintf("\x1b[34;1m|:%s|\x1b[m", typename) : CORD_all("|:", typename, "|"); + } + CORD typename = generic_as_text(NULL, false, item_type); + return CORD_asprintf(colorize ? "\x1b[34;1m|:%s|<%p>\x1b[m" : "|:%s|<%p>", typename, *channel); +} + +// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 |
