]> git.lizzy.rs Git - dragonstd.git/commitdiff
Add flag_sub and flag_uns
authorElias Fleckenstein <eliasfleckenstein@web.de>
Mon, 4 Apr 2022 16:54:18 +0000 (18:54 +0200)
committerElias Fleckenstein <eliasfleckenstein@web.de>
Mon, 4 Apr 2022 16:54:18 +0000 (18:54 +0200)
array.h
bits/compare.c [new file with mode: 0644]
bits/compare.h [new file with mode: 0644]
flag.c
flag.h
list.h
test/Makefile
test/test_refcount_map.c
tree.h

diff --git a/array.h b/array.h
index 8976e7e59f1fd04d690dfb547b551586216fbb24..72c9eb20eee2bc52eb6d88857629b99d5575dd9f 100644 (file)
--- a/array.h
+++ b/array.h
 #ifndef _DRAGONSTD_ARRAY_H_ // include guard
 #define _DRAGONSTD_ARRAY_H_
 
-#include <stddef.h>    // for size_t
-#include <sys/types.h> // for ssize_t
-#include "bits/callback.h"
+#include <stddef.h>        // for size_t
+#include <sys/types.h>     // 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 (file)
index 0000000..650ad7b
--- /dev/null
@@ -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 (file)
index 0000000..96c6044
--- /dev/null
@@ -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 9cc386dd81d50c0e3f1b2a376caf4e8d65d32f56..a8bb87888f5ee67f3b7752f80269718fe1d108ea 100644 (file)
--- 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 78c5ac14e91b51d58f7e4ac46bf666e0c5776cf0..ba6a859e644a91ec449d5d7f0b9f9a3f258f0549 100644 (file)
--- a/flag.h
+++ b/flag.h
 #include <pthread.h>   // for pthread_mutex_t, pthread_cond_t
 #include <stdatomic.h> // for atomic_bool
 #include <stdbool.h>   // 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 d57f3781866135c6955301657bc8454e999e9fd8..e9f3b4b68a0f095fde1f2d8c923e3504c8f2e85d 100644 (file)
--- 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)
 
index 9882da51b818da9a839c69dbc188fbd0533f84da..2de1f9a8167c19525271dba85828ec37e965a135 100644 (file)
@@ -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
index 9333c00ebbb38ee30e58dbe227bab5935101d6ec..642f15b6bd799eb2f8de73db17ad80e2b765cb0b 100644 (file)
@@ -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 d2533214ce5c32dcf475269568757875e03fe0d8..94fce315c8a7ddc1b955d1a3e57f783db3ed8f94 100644 (file)
--- 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 */