From 8e076f8543408337aab96b7010722f5597ba4836 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Tue, 7 Mar 2023 12:43:31 +0100 Subject: [PATCH] feat(cat-heap): initial implementation --- include/vieter_cat_heap.h | 30 ++++++ include/vieter_job_queue.h | 17 ++++ src/cat-heap/README.md | 4 + src/cat-heap/vieter_cat_heap.c | 107 ++++++++++++++++++++++ src/cat-heap/vieter_cat_heap_internal.h | 10 ++ src/job-queue/vieter_job_queue.c | 13 +++ src/job-queue/vieter_job_queue_internal.h | 2 + 7 files changed, 183 insertions(+) create mode 100644 include/vieter_cat_heap.h create mode 100644 src/cat-heap/README.md create mode 100644 src/cat-heap/vieter_cat_heap.c create mode 100644 src/cat-heap/vieter_cat_heap_internal.h diff --git a/include/vieter_cat_heap.h b/include/vieter_cat_heap.h new file mode 100644 index 0000000..d6b2a83 --- /dev/null +++ b/include/vieter_cat_heap.h @@ -0,0 +1,30 @@ +#ifndef VIETER_CAT_HEAP +#define VIETER_CAT_HEAP + +#include + +typedef struct vieter_cat_heap vieter_cat_heap; + +typedef enum vieter_cat_heap_error { + vieter_cat_heap_ok = 0, + vieter_cat_heap_arch_empty = 1, + vieter_cat_heap_arch_not_found = 2 +} vieter_cat_heap_error; + +vieter_cat_heap *vieter_cat_heap_init(); + +void vieter_cat_heap_free(vieter_cat_heap **ptp); + +uint64_t vieter_cat_heap_size(vieter_cat_heap *cheap); + +vieter_cat_heap_error vieter_cat_heap_insert(vieter_cat_heap *cheap, + char *category, uint64_t key, + void *data); + +vieter_cat_heap_error vieter_cat_heap_pop(void **out, vieter_cat_heap *cheap, + char *category); + +vieter_cat_heap_error vieter_cat_heap_peek(void **out, vieter_cat_heap *cheap, + char *category); + +#endif diff --git a/include/vieter_job_queue.h b/include/vieter_job_queue.h index 6cd748f..92ef35f 100644 --- a/include/vieter_job_queue.h +++ b/include/vieter_job_queue.h @@ -123,5 +123,22 @@ vieter_job_queue_remove(vieter_job **out, vieter_job_queue *queue, uint64_t id); */ vieter_job_queue_error vieter_job_queue_fail(vieter_job_queue *queue, uint64_t id, char *report_message); +/* + * Acquire a read lock on the job queue. Return value is the result of + * pthread_rwlock_rdlock. + */ +int vieter_job_queue_rlock(vieter_job_queue *job_queue); + +/* + * Acquire a write lock on the job queue. Return value is the result of + * pthread_rwlock_wrlock. + */ +int vieter_job_queue_wlock(vieter_job_queue *job_queue); + +/* + * Unlock the lock after having acquired it. Return value is the result of + * pthread_rwlock_unlock. + */ +int vieter_job_queue_unlock(vieter_job_queue *job_queue); #endif diff --git a/src/cat-heap/README.md b/src/cat-heap/README.md new file mode 100644 index 0000000..bbdfa0b --- /dev/null +++ b/src/cat-heap/README.md @@ -0,0 +1,4 @@ +A category heap consists of a collection of heaps, with each heap representing +a certain category. In practice, this category would be an architecture (e.g. +`x86_64`). This is used by the job queue to have a queue for each architecture +for a given state. diff --git a/src/cat-heap/vieter_cat_heap.c b/src/cat-heap/vieter_cat_heap.c new file mode 100644 index 0000000..b514b5b --- /dev/null +++ b/src/cat-heap/vieter_cat_heap.c @@ -0,0 +1,107 @@ +#include "vieter_cat_heap_internal.h" + +vieter_cat_heap *vieter_cat_heap_init() { + return calloc(1, sizeof(vieter_cat_heap)); +} + +void vieter_cat_heap_free(vieter_cat_heap **ptp) { + vieter_cat_heap *cheap = *ptp; + + if (cheap->cat_count > 0) { + for (uint64_t i = 0; i < cheap->cat_count; i++) { + free(cheap->categories[i]); + vieter_heap_free(cheap->heaps[i]); + } + + free(cheap->categories); + free(cheap->heaps); + } + + free(cheap); + *ptp = NULL; +} + +uint64_t vieter_cat_heap_size(vieter_cat_heap *cheap) { + uint64_t total = 0; + + for (uint64_t i = 0; i < cheap->cat_count; i++) { + total += vieter_heap_size(cheap->heaps[i]); + } + + return total; +} + +vieter_cat_heap_error vieter_cat_heap_insert(vieter_cat_heap *cheap, + char *category, uint64_t key, + void *data) { + uint64_t i = 0; + + // For now, we do a linear search through all categories. This is more than + // fast enough for most usecases. + while (i < cheap->cat_count && strcmp(category, cheap->categories[i]) != 0) { + i++; + } + + if (i == cheap->cat_count) { + if (cheap->cat_count == 0) { + cheap->categories = malloc(sizeof(char *)); + cheap->heaps = malloc(sizeof(vieter_heap *)); + } else { + cheap->categories = + realloc(cheap->categories, sizeof(char *) * (cheap->cat_count + 1)); + cheap->heaps = + realloc(cheap->heaps, sizeof(vieter_heap *) * (cheap->cat_count + 1)); + } + + cheap->cat_count++; + + cheap->categories[i] = strdup(category); + cheap->heaps[i] = vieter_heap_init(); + } + + vieter_heap_insert(cheap->heaps[i], key, data); + + return vieter_cat_heap_ok; +} + +vieter_cat_heap_error vieter_cat_heap_pop(void **out, vieter_cat_heap *cheap, + char *category) { + uint64_t i = 0; + + while (i < cheap->cat_count && strcmp(category, cheap->categories[i]) != 0) { + i++; + } + + if (i == cheap->cat_count) { + return vieter_cat_heap_arch_not_found; + } + + vieter_heap_error res = vieter_heap_pop(out, cheap->heaps[i]); + + if (res != vieter_heap_ok) { + return vieter_cat_heap_arch_empty; + } + + return vieter_cat_heap_ok; +} + +vieter_cat_heap_error vieter_cat_heap_peek(void **out, vieter_cat_heap *cheap, + char *category) { + uint64_t i = 0; + + while (i < cheap->cat_count && strcmp(category, cheap->categories[i]) != 0) { + i++; + } + + if (i == cheap->cat_count) { + return vieter_cat_heap_arch_not_found; + } + + vieter_heap_error res = vieter_heap_peek(out, cheap->heaps[i]); + + if (res != vieter_heap_ok) { + return vieter_cat_heap_arch_empty; + } + + return vieter_cat_heap_ok; +} diff --git a/src/cat-heap/vieter_cat_heap_internal.h b/src/cat-heap/vieter_cat_heap_internal.h new file mode 100644 index 0000000..a4a3f2c --- /dev/null +++ b/src/cat-heap/vieter_cat_heap_internal.h @@ -0,0 +1,10 @@ +#include "vieter_cat_heap.h" +#include "vieter_heap.h" +#include +#include + +struct vieter_cat_heap { + uint64_t cat_count; + char **categories; + vieter_heap **heaps; +}; diff --git a/src/job-queue/vieter_job_queue.c b/src/job-queue/vieter_job_queue.c index 14ae1dc..a5fb9e3 100644 --- a/src/job-queue/vieter_job_queue.c +++ b/src/job-queue/vieter_job_queue.c @@ -63,6 +63,7 @@ vieter_job_queue_error vieter_job_queue_insert(vieter_job_queue *queue, vieter_job_queue_error vieter_job_queue_pop(vieter_job **out, vieter_job_queue *queue, vieter_job_state state) { + vieter_heap_error res = vieter_heap_pop((void **)out, queue->heaps[state]); if (res != vieter_heap_ok) { @@ -151,3 +152,15 @@ vieter_job_queue_error vieter_job_queue_fail(vieter_job_queue *queue, return vieter_job_queue_ok; } + +int vieter_job_queue_rlock(vieter_job_queue *job_queue) { + return pthread_rwlock_rdlock(&job_queue->lock); +} + +int vieter_job_queue_wlock(vieter_job_queue *job_queue) { + return pthread_rwlock_wrlock(&job_queue->lock); +} + +int vieter_job_queue_unlock(vieter_job_queue *job_queue) { + return pthread_rwlock_unlock(&job_queue->lock); +} diff --git a/src/job-queue/vieter_job_queue_internal.h b/src/job-queue/vieter_job_queue_internal.h index dac8b97..4641ba6 100644 --- a/src/job-queue/vieter_job_queue_internal.h +++ b/src/job-queue/vieter_job_queue_internal.h @@ -4,10 +4,12 @@ #include "vieter_heap.h" #include "vieter_job_queue.h" #include "vieter_tree.h" +#include struct vieter_job_queue { vieter_tree *tree; vieter_heap *heaps[VIETER_JOB_STATES]; + pthread_rwlock_t lock; }; #endif