aboutsummaryrefslogtreecommitdiff
path: root/builtins/channel.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-08-11 14:47:34 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-08-11 14:47:34 -0400
commit2ecb5fe885042ca6c25ee0a3e3da070ddec9e07e (patch)
treecdd7c7d1d51982d4074f76a1bccc522fbc8b5eee /builtins/channel.c
parent3bf8ea8e12a2728bf63968ca7b42359b089e318b (diff)
Add channels and threads
Diffstat (limited to 'builtins/channel.c')
-rw-r--r--builtins/channel.c102
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