Commit 88d64d65ab05acf95912f022a693f788e81b9be2
1 parent
7a1cb698
try to make data structures thread save by using a mutex
Showing
25 changed files
with
187 additions
and
57 deletions
... | ... | @@ -28,16 +28,16 @@ |
28 | 28 | #include "trbase.h" |
29 | 29 | #include "tr/tree.h" |
30 | 30 | |
31 | -#define TR_HASH_IS_EMPTY(h) ((h)->root) | |
31 | +#define TR_HASH_IS_EMPTY(h) ((h)->tree->root) | |
32 | 32 | |
33 | 33 | TR_CLASS(TR_Hash) { |
34 | - TR_Tree root; | |
34 | + TR_Tree tree; | |
35 | 35 | int cleanup_no_free; |
36 | 36 | }; |
37 | 37 | TR_INSTANCE_INIT(TR_Hash); |
38 | 38 | TR_CLASSVARS_DECL(TR_Hash) {}; |
39 | 39 | |
40 | -#define TR_hashEmpty(hash) (NULL == (hash)->root) | |
40 | +#define TR_hashEmpty(hash) (NULL == (hash)->tree->root) | |
41 | 41 | |
42 | 42 | void * TR_hashAdd(TR_Hash, void *); |
43 | 43 | void * TR_hashDelete(TR_Hash, const char *, size_t); | ... | ... |
... | ... | @@ -26,6 +26,7 @@ |
26 | 26 | #ifndef __TR_QUEUE_H__ |
27 | 27 | #define __TR_QUEUE_H__ |
28 | 28 | |
29 | +#include <pthread.h> | |
29 | 30 | #include <sys/types.h> |
30 | 31 | |
31 | 32 | #include "trbase.h" |
... | ... | @@ -35,6 +36,8 @@ TR_CLASS(TR_Queue) { |
35 | 36 | void * msg; |
36 | 37 | TR_Queue next; |
37 | 38 | |
39 | + pthread_mutex_t lock; | |
40 | + | |
38 | 41 | /** |
39 | 42 | * first and last are only available in the initial queue |
40 | 43 | * element (the root). This elelment does not contain any message | ... | ... |
... | ... | @@ -23,17 +23,26 @@ |
23 | 23 | #ifndef __TR_TREE_H__ |
24 | 24 | #define __TR_TREE_H__ |
25 | 25 | |
26 | +#include <pthread.h> | |
27 | + | |
26 | 28 | #include "tr/tree_macros.h" |
27 | 29 | #include "trbase.h" |
28 | 30 | |
29 | -TR_CLASS(TR_Tree) { | |
31 | +TR_CLASS(TR_TreeNode) { | |
30 | 32 | void * data; |
31 | 33 | |
32 | 34 | TR_rbColor color; |
33 | 35 | |
34 | - TR_Tree parent; | |
35 | - TR_Tree left; | |
36 | - TR_Tree right; | |
36 | + TR_TreeNode parent; | |
37 | + TR_TreeNode left; | |
38 | + TR_TreeNode right; | |
39 | +}; | |
40 | +TR_INSTANCE_INIT(TR_TreeNode); | |
41 | +TR_CLASSVARS_DECL(TR_TreeNode) {}; | |
42 | + | |
43 | +TR_CLASS(TR_Tree) { | |
44 | + TR_TreeNode root; | |
45 | + pthread_mutex_t lock; | |
37 | 46 | }; |
38 | 47 | TR_INSTANCE_INIT(TR_Tree); |
39 | 48 | TR_CLASSVARS_DECL(TR_Tree) {}; |
... | ... | @@ -42,10 +51,10 @@ typedef int (*TR_TreeComp)(const void *, const void *); |
42 | 51 | typedef void (*TR_TreeAction)(const void *, const void *, const int); |
43 | 52 | |
44 | 53 | void * TR_treeFind(TR_Tree, const void *, TR_TreeComp); |
45 | -void * TR_treeInsert(TR_Tree *, const void *, TR_TreeComp); | |
46 | -void * TR_treeDelete(TR_Tree *, const void *, TR_TreeComp); | |
54 | +void * TR_treeInsert(TR_Tree, const void *, TR_TreeComp); | |
55 | +void * TR_treeDelete(TR_Tree, const void *, TR_TreeComp); | |
47 | 56 | void TR_treeWalk(TR_Tree, const void *, TR_TreeAction); |
48 | -void TR_treeDestroy(TR_Tree *, TR_TreeAction); | |
57 | +void TR_treeDestroy(TR_Tree, TR_TreeAction); | |
49 | 58 | |
50 | 59 | #endif // __TR_TREE_H__ |
51 | 60 | ... | ... |
... | ... | @@ -11,7 +11,7 @@ TRDATALIBS = cbuf/libcbuf.la \ |
11 | 11 | lib_LTLIBRARIES = libtrdata.la |
12 | 12 | |
13 | 13 | libtrdata_la_SOURCES = |
14 | -libtrdata_la_CFLAGS = $(AM_CFLAGS) | |
14 | +libtrdata_la_CFLAGS = $(AM_CFLAGS) -lpthread | |
15 | 15 | libtrdata_la_LIBADD = $(TRDATALIBS) |
16 | 16 | |
17 | 17 | SUBDIRS = cbuf hash queue tree | ... | ... |
... | ... | @@ -48,7 +48,7 @@ hashAddComp(const void * a, const void * b) |
48 | 48 | void * |
49 | 49 | TR_hashAdd(TR_Hash this, void * operand) |
50 | 50 | { |
51 | - void * found = TR_treeInsert(&this->root, operand, hashAddComp); | |
51 | + void * found = TR_treeInsert(this->tree, operand, hashAddComp); | |
52 | 52 | |
53 | 53 | if (NULL == found) { |
54 | 54 | return NULL; | ... | ... |
... | ... | @@ -36,10 +36,12 @@ void |
36 | 36 | TR_hashCleanup(TR_Hash this) |
37 | 37 | { |
38 | 38 | if (this->cleanup_no_free) { |
39 | - TR_treeDestroy(&(this->root), NULL); | |
39 | + TR_treeDestroy(this->tree, NULL); | |
40 | 40 | } else { |
41 | - TR_treeDestroy(&(this->root), tDelete); | |
41 | + TR_treeDestroy(this->tree, tDelete); | |
42 | 42 | } |
43 | + | |
44 | + TR_delete(this->tree); | |
43 | 45 | } |
44 | 46 | |
45 | 47 | // vim: set ts=4 sw=4: | ... | ... |
... | ... | @@ -51,7 +51,7 @@ TR_hashDelete(TR_Hash this, const char * search, size_t nsearch) |
51 | 51 | unsigned long hash = TR_sdbm((const unsigned char *)search, nsearch); |
52 | 52 | void * found = NULL; |
53 | 53 | |
54 | - found = TR_treeDelete(&(this->root), &hash, hashDeleteComp); | |
54 | + found = TR_treeDelete(this->tree, &hash, hashDeleteComp); | |
55 | 55 | |
56 | 56 | return found; |
57 | 57 | } |
... | ... | @@ -59,7 +59,7 @@ TR_hashDelete(TR_Hash this, const char * search, size_t nsearch) |
59 | 59 | void * |
60 | 60 | TR_hashDeleteByVal(TR_Hash this, unsigned long hash) |
61 | 61 | { |
62 | - void * found = TR_treeDelete(&(this->root), &hash, hashDeleteComp); | |
62 | + void * found = TR_treeDelete(this->tree, &hash, hashDeleteComp); | |
63 | 63 | |
64 | 64 | return found; |
65 | 65 | } | ... | ... |
... | ... | @@ -52,7 +52,7 @@ void * |
52 | 52 | TR_hashGet(TR_Hash this, const char * search, size_t nsearch) |
53 | 53 | { |
54 | 54 | unsigned long hash = TR_sdbm((const unsigned char *)search, nsearch); |
55 | - void * found = TR_treeFind(this->root, &hash, hashGetComp); | |
55 | + void * found = TR_treeFind(this->tree, &hash, hashGetComp); | |
56 | 56 | |
57 | 57 | return found; |
58 | 58 | } |
... | ... | @@ -60,7 +60,7 @@ TR_hashGet(TR_Hash this, const char * search, size_t nsearch) |
60 | 60 | void * |
61 | 61 | TR_hashGetByVal(TR_Hash this, unsigned long hash) |
62 | 62 | { |
63 | - void * found = TR_treeFind(this->root, &hash, hashGetComp); | |
63 | + void * found = TR_treeFind(this->tree, &hash, hashGetComp); | |
64 | 64 | |
65 | 65 | return found; |
66 | 66 | } | ... | ... |
... | ... | @@ -31,6 +31,10 @@ static |
31 | 31 | int |
32 | 32 | hashCtor(void * _this, va_list * params) |
33 | 33 | { |
34 | + TR_Hash this = _this; | |
35 | + | |
36 | + this->tree = TR_new(TR_Tree); | |
37 | + | |
34 | 38 | return 0; |
35 | 39 | } |
36 | 40 | |
... | ... | @@ -41,6 +45,8 @@ hashDtor(void * _this) |
41 | 45 | TR_Hash this = _this; |
42 | 46 | |
43 | 47 | TR_hashCleanup(this); |
48 | + | |
49 | + TR_delete(this->tree); | |
44 | 50 | } |
45 | 51 | |
46 | 52 | TR_INIT_IFACE(TR_Class, hashCtor, hashDtor, NULL); | ... | ... |
... | ... | @@ -26,9 +26,16 @@ |
26 | 26 | void |
27 | 27 | TR_queueDelete(TR_Queue this, void * msg) |
28 | 28 | { |
29 | - TR_Queue node, parent = TR_queueFindParent(this, msg); | |
29 | + TR_Queue node, parent; | |
30 | + | |
31 | + pthread_mutex_lock(&(this->lock)); | |
30 | 32 | |
31 | - if (! parent) return; | |
33 | + parent = TR_queueFindParent(this, msg); | |
34 | + | |
35 | + if (! parent) { | |
36 | + pthread_mutex_unlock(&(this->lock)); | |
37 | + return; | |
38 | + } | |
32 | 39 | |
33 | 40 | node = parent->next; |
34 | 41 | parent->next = node->next; |
... | ... | @@ -40,6 +47,8 @@ TR_queueDelete(TR_Queue this, void * msg) |
40 | 47 | } |
41 | 48 | TR_delete(node); |
42 | 49 | this->nmsg--; |
50 | + | |
51 | + pthread_mutex_unlock(&(this->lock)); | |
43 | 52 | } |
44 | 53 | |
45 | 54 | // vim: set ts=4 sw=4: | ... | ... |
... | ... | @@ -21,6 +21,7 @@ |
21 | 21 | */ |
22 | 22 | |
23 | 23 | #include <stdarg.h> |
24 | +#include <pthread.h> | |
24 | 25 | |
25 | 26 | #include "trbase.h" |
26 | 27 | #include "tr/queue.h" |
... | ... | @@ -30,6 +31,8 @@ TR_queueDestroy(TR_Queue this) |
30 | 31 | { |
31 | 32 | TR_Queue node = this->first; |
32 | 33 | |
34 | + pthread_mutex_lock(&(this->lock)); | |
35 | + | |
33 | 36 | while (NULL != node) { |
34 | 37 | TR_Queue next = node->next; |
35 | 38 | if (this->free_msgs) { |
... | ... | @@ -41,6 +44,8 @@ TR_queueDestroy(TR_Queue this) |
41 | 44 | |
42 | 45 | this->first = this->next = this->last = NULL; |
43 | 46 | this->nmsg = 0; |
47 | + | |
48 | + pthread_mutex_unlock(&(this->lock)); | |
44 | 49 | } |
45 | 50 | |
46 | 51 | // vim: set ts=4 sw=4: | ... | ... |
... | ... | @@ -20,6 +20,8 @@ |
20 | 20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
21 | 21 | */ |
22 | 22 | |
23 | +#include <pthread.h> | |
24 | + | |
23 | 25 | #include "trbase.h" |
24 | 26 | #include "tr/queue.h" |
25 | 27 | |
... | ... | @@ -29,7 +31,10 @@ TR_queueGet(TR_Queue this) |
29 | 31 | TR_Queue first; |
30 | 32 | void * msg; |
31 | 33 | |
34 | + pthread_mutex_lock(&(this->lock)); | |
35 | + | |
32 | 36 | if (NULL == this->first) { |
37 | + pthread_mutex_unlock(&(this->lock)); | |
33 | 38 | return NULL; |
34 | 39 | } |
35 | 40 | |
... | ... | @@ -45,6 +50,8 @@ TR_queueGet(TR_Queue this) |
45 | 50 | this->first = first; |
46 | 51 | this->nmsg--; |
47 | 52 | |
53 | + pthread_mutex_unlock(&(this->lock)); | |
54 | + | |
48 | 55 | return msg; |
49 | 56 | } |
50 | 57 | ... | ... |
... | ... | @@ -20,6 +20,8 @@ |
20 | 20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
21 | 21 | */ |
22 | 22 | |
23 | +#include <pthread.h> | |
24 | + | |
23 | 25 | #include "trbase.h" |
24 | 26 | #include "tr/queue.h" |
25 | 27 | |
... | ... | @@ -28,6 +30,8 @@ TR_queuePut(TR_Queue this, void * msg) |
28 | 30 | { |
29 | 31 | TR_Queue node = (this->last)? this->last : this; |
30 | 32 | |
33 | + pthread_mutex_lock(&(this->lock)); | |
34 | + | |
31 | 35 | node->next = TR_new(TR_Queue); |
32 | 36 | this->last = node->next; |
33 | 37 | |
... | ... | @@ -37,6 +41,8 @@ TR_queuePut(TR_Queue this, void * msg) |
37 | 41 | |
38 | 42 | node->next->msg = msg; |
39 | 43 | this->nmsg++; |
44 | + | |
45 | + pthread_mutex_unlock(&(this->lock)); | |
40 | 46 | } |
41 | 47 | |
42 | 48 | // vim: set ts=4 sw=4: | ... | ... |
... | ... | @@ -20,6 +20,8 @@ |
20 | 20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
21 | 21 | */ |
22 | 22 | |
23 | +#include <pthread.h> | |
24 | + | |
23 | 25 | #include "trbase.h" |
24 | 26 | #include "tr/queue.h" |
25 | 27 | |
... | ... | @@ -28,11 +30,15 @@ TR_queuePutFirst(TR_Queue this, void * msg) |
28 | 30 | { |
29 | 31 | TR_Queue current_first = this->first; |
30 | 32 | |
33 | + pthread_mutex_lock(&(this->lock)); | |
34 | + | |
31 | 35 | this->first = this->next = TR_new(TR_Queue); |
32 | 36 | this->first->next = current_first; |
33 | 37 | this->first->msg = msg; |
34 | 38 | this->last = this->last ? this->last : this->first; |
35 | 39 | this->nmsg++; |
40 | + | |
41 | + pthread_mutex_unlock(&(this->lock)); | |
36 | 42 | } |
37 | 43 | |
38 | 44 | // vim: set ts=4 sw=4: | ... | ... |
... | ... | @@ -21,6 +21,7 @@ |
21 | 21 | */ |
22 | 22 | |
23 | 23 | #include <stdarg.h> |
24 | +#include <pthread.h> | |
24 | 25 | |
25 | 26 | #include "trbase.h" |
26 | 27 | #include "tr/queue.h" |
... | ... | @@ -32,6 +33,7 @@ queueCtor(void * _this, va_list * params) |
32 | 33 | TR_Queue this = _this; |
33 | 34 | |
34 | 35 | this->free_msgs = 1; |
36 | + pthread_mutex_init(&(this->lock), NULL); | |
35 | 37 | |
36 | 38 | return 0; |
37 | 39 | } |
... | ... | @@ -40,7 +42,10 @@ static |
40 | 42 | void |
41 | 43 | queueDtor(void * _this) |
42 | 44 | { |
43 | - TR_queueDestroy((TR_Queue)_this); | |
45 | + TR_Queue this = _this; | |
46 | + | |
47 | + TR_queueDestroy(this); | |
48 | + pthread_mutex_destroy(&(this->lock)); | |
44 | 49 | } |
45 | 50 | |
46 | 51 | TR_INIT_IFACE(TR_Class, queueCtor, queueDtor, NULL); | ... | ... |
... | ... | @@ -20,18 +20,21 @@ |
20 | 20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
21 | 21 | */ |
22 | 22 | |
23 | +#include <pthread.h> | |
24 | + | |
23 | 25 | #include "trbase.h" |
24 | 26 | #include "tr/tree.h" |
25 | 27 | |
26 | 28 | void * |
27 | -TR_treeDelete(TR_Tree * this, const void * search, TR_TreeComp comp) | |
29 | +TR_treeDelete(TR_Tree this, const void * search, TR_TreeComp comp) | |
28 | 30 | { |
29 | - TR_Tree node = *this; | |
30 | - TR_Tree del_node; | |
31 | - TR_Tree sibling; | |
32 | - int found; | |
31 | + TR_TreeNode node = this->root; | |
32 | + TR_TreeNode del_node; | |
33 | + TR_TreeNode sibling; | |
34 | + int found; | |
35 | + void * data; | |
33 | 36 | |
34 | - void * data; | |
37 | + pthread_mutex_lock(&(this->lock)); | |
35 | 38 | |
36 | 39 | TR_TREE_FIND(node, search, found, comp); |
37 | 40 | |
... | ... | @@ -39,6 +42,7 @@ TR_treeDelete(TR_Tree * this, const void * search, TR_TreeComp comp) |
39 | 42 | * nothing was found...return NULL to indicate this. |
40 | 43 | */ |
41 | 44 | if (found != 0) { |
45 | + pthread_mutex_unlock(&(this->lock)); | |
42 | 46 | return NULL; |
43 | 47 | } |
44 | 48 | |
... | ... | @@ -57,7 +61,7 @@ TR_treeDelete(TR_Tree * this, const void * search, TR_TreeComp comp) |
57 | 61 | * out inOrderSuccessor and remove the inOrderSuccessor. |
58 | 62 | */ |
59 | 63 | if (NULL != TR_TREE_LEFT(node) && NULL != TR_TREE_RIGHT(node)) { |
60 | - TR_Tree successor; | |
64 | + TR_TreeNode successor; | |
61 | 65 | |
62 | 66 | TR_TREE_INORDER_SUCC(node, successor); |
63 | 67 | |
... | ... | @@ -66,12 +70,12 @@ TR_treeDelete(TR_Tree * this, const void * search, TR_TreeComp comp) |
66 | 70 | } |
67 | 71 | |
68 | 72 | { |
69 | - TR_Tree child = TR_TREE_CHILD(node); | |
73 | + TR_TreeNode child = TR_TREE_CHILD(node); | |
70 | 74 | |
71 | 75 | /* |
72 | 76 | * if we still have one child replace ourself with it. |
73 | 77 | */ |
74 | - TR_TREE_REPLACE_NODE(this, node, child); | |
78 | + TR_TREE_REPLACE_NODE(&(this->root), node, child); | |
75 | 79 | |
76 | 80 | /* |
77 | 81 | * and finally delete the node...and prepare ourselfs |
... | ... | @@ -81,6 +85,7 @@ TR_treeDelete(TR_Tree * this, const void * search, TR_TreeComp comp) |
81 | 85 | if (NULL != child && rbRed == child->color) { |
82 | 86 | child->color = rbBlack; |
83 | 87 | TR_delete(node); |
88 | + pthread_mutex_unlock(&(this->lock)); | |
84 | 89 | return data; |
85 | 90 | } else { |
86 | 91 | del_node = node; |
... | ... | @@ -94,6 +99,7 @@ TR_treeDelete(TR_Tree * this, const void * search, TR_TreeComp comp) |
94 | 99 | } |
95 | 100 | } else { |
96 | 101 | TR_delete(node); |
102 | + pthread_mutex_unlock(&(this->lock)); | |
97 | 103 | return data; |
98 | 104 | } |
99 | 105 | } |
... | ... | @@ -105,9 +111,12 @@ TR_treeDelete(TR_Tree * this, const void * search, TR_TreeComp comp) |
105 | 111 | * rebalancing process...(this does not make much sense, but |
106 | 112 | * to be honest I don't know now.) |
107 | 113 | */ |
108 | - TR_TREE_BALANCE_DELETE(this, node, sibling); | |
114 | + TR_TREE_BALANCE_DELETE(&(this->root), node, sibling); | |
109 | 115 | |
110 | 116 | TR_delete(del_node); |
117 | + | |
118 | + pthread_mutex_unlock(&(this->lock)); | |
119 | + | |
111 | 120 | return data; |
112 | 121 | } |
113 | 122 | ... | ... |
... | ... | @@ -24,11 +24,11 @@ |
24 | 24 | #include "tr/tree.h" |
25 | 25 | |
26 | 26 | void |
27 | -TR_treeDestroy(TR_Tree * this, TR_TreeAction action) | |
27 | +TR_treeDestroy(TR_Tree this, TR_TreeAction action) | |
28 | 28 | { |
29 | - TR_Tree previous = * this; | |
30 | - TR_Tree node = * this; | |
31 | - int depth = 1; | |
29 | + TR_TreeNode previous = this->root; | |
30 | + TR_TreeNode node = this->root; | |
31 | + int depth = 1; | |
32 | 32 | |
33 | 33 | /* |
34 | 34 | * I think this has something like O(n+log(n)) on a ballanced |
... | ... | @@ -44,7 +44,7 @@ TR_treeDestroy(TR_Tree * this, TR_TreeAction action) |
44 | 44 | || previous == TR_TREE_LEFT(node)) && NULL == TR_TREE_RIGHT(node)) |
45 | 45 | || previous == TR_TREE_RIGHT(node)) { |
46 | 46 | |
47 | - TR_Tree parent = TR_TREE_PARENT(node); | |
47 | + TR_TreeNode parent = TR_TREE_PARENT(node); | |
48 | 48 | |
49 | 49 | if (action) { |
50 | 50 | action(node->data, NULL, depth); |
... | ... | @@ -82,7 +82,7 @@ TR_treeDestroy(TR_Tree * this, TR_TreeAction action) |
82 | 82 | } |
83 | 83 | } |
84 | 84 | |
85 | - *this = NULL; | |
85 | + this->root = NULL; | |
86 | 86 | } |
87 | 87 | |
88 | 88 | // vim: set ts=4 sw=4: | ... | ... |
... | ... | @@ -25,11 +25,16 @@ |
25 | 25 | void * |
26 | 26 | TR_treeFind(TR_Tree this, const void * search, TR_TreeComp comp) |
27 | 27 | { |
28 | - int found; | |
28 | + int found; | |
29 | + TR_TreeNode node = this->root; | |
29 | 30 | |
30 | - TR_TREE_FIND(this, search, found, comp); | |
31 | + pthread_mutex_lock(&(this->lock)); | |
31 | 32 | |
32 | - return found == 0 ? this->data : NULL; | |
33 | + TR_TREE_FIND(node, search, found, comp); | |
34 | + | |
35 | + pthread_mutex_unlock(&(this->lock)); | |
36 | + | |
37 | + return found == 0 ? node->data : NULL; | |
33 | 38 | } |
34 | 39 | |
35 | 40 | // vim: set ts=4 sw=4: | ... | ... |
... | ... | @@ -20,16 +20,20 @@ |
20 | 20 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
21 | 21 | */ |
22 | 22 | |
23 | +#include <pthread.h> | |
24 | + | |
23 | 25 | #include "trbase.h" |
24 | 26 | #include "tr/tree.h" |
25 | 27 | |
26 | 28 | void * |
27 | -TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp) | |
29 | +TR_treeInsert(TR_Tree this, const void * search, TR_TreeComp comp) | |
28 | 30 | { |
29 | - TR_Tree node = *this; | |
30 | - TR_Tree new_node = NULL; | |
31 | + TR_TreeNode node = this->root; | |
32 | + TR_TreeNode new_node = NULL; | |
31 | 33 | int found; |
32 | 34 | |
35 | + pthread_mutex_lock(&(this->lock)); | |
36 | + | |
33 | 37 | /* |
34 | 38 | * insert the node or return the one in tree if comparison |
35 | 39 | * succeeds. |
... | ... | @@ -39,11 +43,13 @@ TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp) |
39 | 43 | * if the root is NULL we simple add the element and set |
40 | 44 | * node to it. |
41 | 45 | */ |
42 | - *this = node = new_node = TR_new(TR_Tree, search); | |
46 | + this->root = node = new_node = TR_new(TR_TreeNode, search); | |
43 | 47 | } else { |
44 | 48 | TR_TREE_FIND(node, search, found, comp); |
45 | 49 | |
46 | 50 | if (found == 0) { |
51 | + pthread_mutex_unlock(&(this->lock)); | |
52 | + | |
47 | 53 | // This differs from tsearch, which is the posix equivalent to |
48 | 54 | // this function in that it will not replace an existing value. |
49 | 55 | // If there is a value for the given key in the tree it will be |
... | ... | @@ -55,11 +61,11 @@ TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp) |
55 | 61 | } else { |
56 | 62 | // not found |
57 | 63 | if (0 < found) { |
58 | - node->left = TR_new(TR_Tree, search); | |
64 | + node->left = TR_new(TR_TreeNode, search); | |
59 | 65 | node->left->parent = node; |
60 | 66 | node = new_node = node->left; |
61 | 67 | } else { |
62 | - node->right = TR_new(TR_Tree, search); | |
68 | + node->right = TR_new(TR_TreeNode, search); | |
63 | 69 | node->right->parent = node; |
64 | 70 | node = new_node = node->right; |
65 | 71 | } |
... | ... | @@ -70,7 +76,9 @@ TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp) |
70 | 76 | * we expect node not to be NULL and pointing to our |
71 | 77 | * new node at this point...now rabalance the tree |
72 | 78 | */ |
73 | - TR_TREE_BALANCE_INSERT(this, node); | |
79 | + TR_TREE_BALANCE_INSERT(&(this->root), node); | |
80 | + | |
81 | + pthread_mutex_unlock(&(this->lock)); | |
74 | 82 | |
75 | 83 | return new_node->data; |
76 | 84 | } | ... | ... |
... | ... | @@ -33,11 +33,8 @@ treeCtor(void * _this, va_list * params) |
33 | 33 | { |
34 | 34 | TR_Tree this = _this; |
35 | 35 | |
36 | - this->data = va_arg(*params, void *); | |
37 | - this->color = rbRed; | |
38 | - this->parent = NULL; | |
39 | - this->left = NULL; | |
40 | - this->right = NULL; | |
36 | + this->root = NULL; | |
37 | + pthread_mutex_init(&(this->lock), NULL); | |
41 | 38 | |
42 | 39 | return 0; |
43 | 40 | } |
... | ... | @@ -46,6 +43,8 @@ static |
46 | 43 | void |
47 | 44 | treeDtor(void * _this) |
48 | 45 | { |
46 | + TR_Tree this = _this; | |
47 | + pthread_mutex_destroy(&(this->lock)); | |
49 | 48 | } |
50 | 49 | |
51 | 50 | TR_INIT_IFACE(TR_Class, treeCtor, treeDtor, NULL); | ... | ... |
src/tree/tree_node.c
0 → 100644
1 | +/** | |
2 | + * \file | |
3 | + * | |
4 | + * \author Georg Hopp | |
5 | + * | |
6 | + * \copyright | |
7 | + * Copyright © 2014 Georg Hopp | |
8 | + * | |
9 | + * This program is free software: you can redistribute it and/or modify | |
10 | + * it under the terms of the GNU General Public License as published by | |
11 | + * the Free Software Foundation, either version 3 of the License, or | |
12 | + * (at your option) any later version. | |
13 | + * | |
14 | + * This program is distributed in the hope that it will be useful, | |
15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | + * GNU General Public License for more details. | |
18 | + * | |
19 | + * You should have received a copy of the GNU General Public License | |
20 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
21 | + */ | |
22 | + | |
23 | +#define _GNU_SOURCE | |
24 | + | |
25 | +#include <stdarg.h> | |
26 | + | |
27 | +#include "trbase.h" | |
28 | +#include "tr/tree.h" | |
29 | + | |
30 | +static | |
31 | +int | |
32 | +treeNodeCtor(void * _this, va_list * params) | |
33 | +{ | |
34 | + TR_TreeNode this = _this; | |
35 | + | |
36 | + this->data = va_arg(*params, void *); | |
37 | + this->color = rbRed; | |
38 | + this->parent = NULL; | |
39 | + this->left = NULL; | |
40 | + this->right = NULL; | |
41 | + | |
42 | + return 0; | |
43 | +} | |
44 | + | |
45 | +static void treeNodeDtor(void * _this) {} | |
46 | + | |
47 | +TR_INIT_IFACE(TR_Class, treeNodeCtor, treeNodeDtor, NULL); | |
48 | +TR_CREATE_CLASS(TR_TreeNode, NULL, NULL, TR_IF(TR_Class)); | |
49 | + | |
50 | +// vim: set ts=4 sw=4: | ... | ... |
... | ... | @@ -25,9 +25,9 @@ |
25 | 25 | void |
26 | 26 | TR_treeWalk(TR_Tree this, const void * data, TR_TreeAction action) |
27 | 27 | { |
28 | - TR_Tree previous = this; | |
29 | - TR_Tree node = this; | |
30 | - int depth = 1; | |
28 | + TR_TreeNode previous = this->root; | |
29 | + TR_TreeNode node = this->root; | |
30 | + int depth = 1; | |
31 | 31 | |
32 | 32 | while (NULL != node) { |
33 | 33 | if (previous == TR_TREE_RIGHT(node)) { | ... | ... |
Please
register
or
login
to post a comment