#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 */
--- /dev/null
+#include "compare.h"
+
+int cmp_ref(const void *va, const void *vb)
+{
+ return
+ va < vb ? -1 :
+ va > vb ? +1 :
+ 0;
+}
--- /dev/null
+#ifndef _DRAGONSTD_COMPARE_H_
+#define _DRAGONSTD_COMPARE_H_
+
+int cmp_ref(const void *pa, const void *pb);
+
+#endif // _DRAGONSTD_COMPARE_H_
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);
}
#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);
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]
#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)
-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
$(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
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++)
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]);
#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 */