From 5119e374e868c339c87fe1e43cd41a78a81cc537 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Mon, 4 Apr 2022 18:54:18 +0200 Subject: [PATCH] Add flag_sub and flag_uns --- array.h | 7 ++++--- bits/compare.c | 9 +++++++++ bits/compare.h | 6 ++++++ flag.c | 22 +++++++++++++++++++++- flag.h | 22 ++++++++++++++++++++-- list.h | 1 + test/Makefile | 21 +++------------------ test/test_refcount_map.c | 4 ++-- tree.h | 1 + 9 files changed, 67 insertions(+), 26 deletions(-) create mode 100644 bits/compare.c create mode 100644 bits/compare.h diff --git a/array.h b/array.h index 8976e7e..72c9eb2 100644 --- a/array.h +++ b/array.h @@ -10,9 +10,10 @@ #ifndef _DRAGONSTD_ARRAY_H_ // include guard #define _DRAGONSTD_ARRAY_H_ -#include // for size_t -#include // for ssize_t -#include "bits/callback.h" +#include // for size_t +#include // for ssize_t +#include "bits/callback.h" // for Comparator +#include "bits/compare.h" // for cmp_ref (not used in file) typedef struct { /* public */ diff --git a/bits/compare.c b/bits/compare.c new file mode 100644 index 0000000..650ad7b --- /dev/null +++ b/bits/compare.c @@ -0,0 +1,9 @@ +#include "compare.h" + +int cmp_ref(const void *va, const void *vb) +{ + return + va < vb ? -1 : + va > vb ? +1 : + 0; +} diff --git a/bits/compare.h b/bits/compare.h new file mode 100644 index 0000000..96c6044 --- /dev/null +++ b/bits/compare.h @@ -0,0 +1,6 @@ +#ifndef _DRAGONSTD_COMPARE_H_ +#define _DRAGONSTD_COMPARE_H_ + +int cmp_ref(const void *pa, const void *pb); + +#endif // _DRAGONSTD_COMPARE_H_ diff --git a/flag.c b/flag.c index 9cc386d..a8bb878 100644 --- a/flag.c +++ b/flag.c @@ -5,19 +5,39 @@ void flag_ini(Flag *flag) flag->set = false; pthread_cond_init(&flag->cnd, NULL); pthread_mutex_init(&flag->mtx, NULL); + list_ini(&flag->cvs); + flag_sub(flag, &flag->cnd); } void flag_dst(Flag *flag) { pthread_cond_destroy(&flag->cnd); pthread_mutex_destroy(&flag->mtx); + list_clr(&flag->cvs, NULL, NULL, NULL); +} + +void flag_sub(Flag *flag, pthread_cond_t *cnd) +{ + pthread_mutex_lock(&flag->mtx); + list_add(&flag->cvs, cnd, &cmp_ref, NULL); + pthread_mutex_unlock(&flag->mtx); +} + +void flag_uns(Flag *flag, pthread_cond_t *cnd) +{ + pthread_mutex_lock(&flag->mtx); + list_del(&flag->cvs, cnd, &cmp_ref, NULL); + pthread_mutex_unlock(&flag->mtx); } void flag_set(Flag *flag) { pthread_mutex_lock(&flag->mtx); flag->set = true; - pthread_cond_broadcast(&flag->cnd); + + LIST_ITERATE(&flag->cvs, node) + pthread_cond_broadcast(node->dat); + pthread_mutex_unlock(&flag->mtx); } diff --git a/flag.h b/flag.h index 78c5ac1..ba6a859 100644 --- a/flag.h +++ b/flag.h @@ -14,13 +14,15 @@ #include // for pthread_mutex_t, pthread_cond_t #include // for atomic_bool #include // for bool +#include "list.h" // for List typedef struct { /* protected */ atomic_bool set; // whether the flag is set /* private */ - pthread_cond_t cnd; // condition variable used for waiting - pthread_mutex_t mtx; // mutex to protect the condition variable + pthread_cond_t cnd; // main condition variable + pthread_mutex_t mtx; // mutex to protect the main condition variable + List cvs; // condition variables } Flag; void flag_ini(Flag *flag); @@ -38,6 +40,22 @@ void flag_dst(Flag *flag); The refcount is unusable until reinitialized afterwards. */ +void flag_sub(Flag *flag, pthread_cond_t *cnd); +/* + [Thread Safe] + Subscribe condition variable cnd to flag. + + The condition variable will be triggered when the flag is set. +*/ + +void flag_uns(Flag *flag, pthread_cond_t *cnd); +/* + [Thread Safe] + Unsubscribe condition variable cnd from flag. + + The condition variable will no longer be triggered when the flag is set. +*/ + void flag_set(Flag *flag); /* [Thread Safe] diff --git a/list.h b/list.h index d57f378..e9f3b4b 100644 --- a/list.h +++ b/list.h @@ -9,6 +9,7 @@ #define _DRAGONSTD_LIST_H_ #include "bits/callback.h" // for Iterator, Comparator +#include "bits/compare.h" // for cmp_ref (not used in file) #define LIST_ITERATE(list, node) for (ListNode *node = (list)->fst; node != NULL; node = node->nxt) diff --git a/test/Makefile b/test/Makefile index 9882da5..2de1f9a 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,4 +1,4 @@ -CC=cc -g -Wall -Wextra -Werror -fmax-errors=1 -o +CC=cc -g -Wall -Wextra -Werror -fmax-errors=1 TEST=valgrind --leak-check=full --show-leak-kinds=all --quiet run: test_array test_list test_tree test_queue test_flag test_refcount_map @@ -9,23 +9,8 @@ run: test_array test_list test_tree test_queue test_flag test_refcount_map $(TEST) ./test_flag && \ $(TEST) ./test_refcount_map -test_array: test_array.c ../array.c ../array.h ../bits/callback.h - $(CC) test_array test_array.c ../array.c - -test_list: test_list.c ../list.c ../list.h ../bits/callback.h ../bits/wrappers.h - $(CC) test_list test_list.c ../list.c - -test_tree: test_tree.c ../tree.c ../tree.h ../bits/callback.h ../bits/wrappers.h - $(CC) test_tree test_tree.c ../tree.c - -test_queue: test_queue.c ../queue.c ../queue.h ../list.c ../list.h ../bits/callback.h ../bits/wrappers.h - $(CC) test_queue test_queue.c ../queue.c ../list.c -lpthread - -test_flag: test_flag.c ../flag.c ../flag.h - $(CC) test_flag test_flag.c ../flag.c -lpthread - -test_refcount_map: test_refcount_map.c ../refcount.c ../refcount.h ../map.c ../map.h ../tree.c ../tree.h ../bits/callback.h ../bits/wrappers.h - $(CC) test_refcount_map test_refcount_map.c ../refcount.c ../map.c ../tree.c -lpthread +test_%: test_%.c ../*.h ../*.c ../bits/*.h ../bits/*.c + $(CC) $< ../*.c ../bits/*.c -o $@ -lpthread clean: rm -rf test_array test_list test_tree test_queue test_flag test_refcount_map diff --git a/test/test_refcount_map.c b/test/test_refcount_map.c index 9333c00..642f15b 100644 --- a/test/test_refcount_map.c +++ b/test/test_refcount_map.c @@ -126,7 +126,7 @@ int main() for (int j = 0; j < 5; j++) pthread_create(&threads[i][j], NULL, funcs[i], &results[i][j]); - sleep(10); + sleep(1); cancel = true; for (int i = 0; i < 3; i++) @@ -140,7 +140,7 @@ int main() map_cnl(&map, (void *) &refcount_drp, NULL, NULL, 0); map_dst(&map); - printf("Time: 10 seconds\n"); + printf("Time: 1 second\n"); printf("Created objects: %u\n", results[0][0]); printf("Accessed objects: %u\n", results[1][0]); printf("Deleted objects: %u\n", results[2][0]); diff --git a/tree.h b/tree.h index d253321..94fce31 100644 --- a/tree.h +++ b/tree.h @@ -15,6 +15,7 @@ #define _DRAGONSTD_TREE_H_ #include "bits/callback.h" // for Iterator, Comparator +#include "bits/compare.h" // for cmp_ref (not used in file) typedef struct TreeNode { /* public */ -- 2.44.0