Browse Source

use threadsave libc. Prepare code for locks. Separate tree and tree elements. Use c99 standard.

1.0.0
Georg Hopp 11 years ago
parent
commit
daaa2133b2
  1. 3
      configure.ac
  2. 8
      include/tr/hash.h
  3. 22
      include/tr/tree.h
  4. 4
      src/Makefile.am
  5. 4
      src/cbuf/Makefile.am
  6. 4
      src/hash/Makefile.am
  7. 2
      src/hash/add.c
  8. 6
      src/hash/cleanup.c
  9. 4
      src/hash/delete.c
  10. 4
      src/hash/each.c
  11. 4
      src/hash/get.c
  12. 2
      src/hash/get_first.c
  13. 6
      src/hash/hash.c
  14. 16
      src/queue/Makefile.am
  15. 8
      src/queue/delete.c
  16. 4
      src/queue/destroy.c
  17. 4
      src/queue/put.c
  18. 4
      src/queue/put_first.c
  19. 4
      src/queue/queue.c
  20. 7
      src/tree/Makefile.am
  21. 20
      src/tree/delete.c
  22. 13
      src/tree/destroy.c
  23. 8
      src/tree/find.c
  24. 20
      src/tree/insert.c
  25. 6
      src/tree/tree.c
  26. 50
      src/tree/tree_node.c
  27. 13
      src/tree/walk.c

3
configure.ac

@ -53,6 +53,9 @@ AM_CFLAGS="${AM_CFLAGS} ${MEM_OPT_FLAGS}"
AM_CFLAGS="${AM_CFLAGS} ${CFLAGS}"
AC_SUBST(AM_CFLAGS)
AM_LDFLAGS=""
AC_SUBST(AM_LDFLAGS)
AC_CONFIG_FILES([Makefile
docs/Makefile
tests/Makefile

8
include/tr/hash.h

@ -28,16 +28,16 @@
#include "trbase.h"
#include "tr/tree.h"
#define TR_HASH_IS_EMPTY(h) ((h)->root)
#define TR_HASH_IS_EMPTY(h) ((h)->tree->root)
TR_CLASS(TR_Hash) {
TR_Tree root;
TR_Tree tree;
int cleanup_no_free;
};
TR_INSTANCE_INIT(TR_Hash);
TR_CLASSVARS_DECL(TR_Hash) {};
#define TR_hashEmpty(hash) (NULL == (hash)->root)
//#define TR_hashEmpty(hash) (NULL == (hash)->tree->root)
void * TR_hashAdd(TR_Hash, void *);
void * TR_hashDelete(TR_Hash, const char *, size_t);
@ -45,7 +45,7 @@ void * TR_hashGet(TR_Hash, const char *, size_t);
void * TR_hashGetFirst(TR_Hash);
void * TR_hashDeleteByVal(TR_Hash, unsigned long);
void * TR_hashGetByVal(TR_Hash, unsigned long);
void TR_hashEach(TR_Hash, const void *, void (*)(const void *, const void *));
unsigned long TR_hashEach(TR_Hash, const void *, void (*)(const void *, const void *));
void TR_hashCleanup(TR_Hash);
#endif // __TR_HASH_H__

22
include/tr/tree.h

@ -26,14 +26,20 @@
#include "tr/tree_macros.h"
#include "trbase.h"
TR_CLASS(TR_Tree) {
TR_CLASS(TR_TreeNode) {
void * data;
TR_rbColor color;
TR_Tree parent;
TR_Tree left;
TR_Tree right;
TR_TreeNode parent;
TR_TreeNode left;
TR_TreeNode right;
};
TR_INSTANCE_INIT(TR_TreeNode);
TR_CLASSVARS_DECL(TR_TreeNode) {};
TR_CLASS(TR_Tree) {
TR_TreeNode root;
};
TR_INSTANCE_INIT(TR_Tree);
TR_CLASSVARS_DECL(TR_Tree) {};
@ -42,10 +48,10 @@ typedef int (*TR_TreeComp)(const void *, const void *);
typedef void (*TR_TreeAction)(const void *, const void *, const int);
void * TR_treeFind(TR_Tree, const void *, TR_TreeComp);
void * TR_treeInsert(TR_Tree *, const void *, TR_TreeComp);
void * TR_treeDelete(TR_Tree *, const void *, TR_TreeComp);
void TR_treeWalk(TR_Tree, const void *, TR_TreeAction);
void TR_treeDestroy(TR_Tree *, TR_TreeAction);
void * TR_treeInsert(TR_Tree, const void *, TR_TreeComp);
void * TR_treeDelete(TR_Tree, const void *, TR_TreeComp);
unsigned long TR_treeWalk(TR_Tree, const void *, TR_TreeAction);
void TR_treeDestroy(TR_Tree, TR_TreeAction);
#endif // __TR_TREE_H__

4
src/Makefile.am

@ -1,7 +1,8 @@
ACLOCAL_AMFLAGS = -I m4
AUTOMAKE_OPTIONS = subdir-objects
AM_CFLAGS += -I../include/
AM_CFLAGS += -I../include/ -std=c99 -DREENTRANT -lpthread
AM_LDFLAGS += -lpthread
TRDATALIBS = cbuf/libcbuf.la \
hash/libhash.la \
@ -13,5 +14,6 @@ lib_LTLIBRARIES = libtrdata.la
libtrdata_la_SOURCES =
libtrdata_la_CFLAGS = $(AM_CFLAGS)
libtrdata_la_LIBADD = $(TRDATALIBS)
libtrdata_la_LDFLAGS = -version-info 0:0:0 $(AM_LDFLAGS)
SUBDIRS = cbuf hash queue tree

4
src/cbuf/Makefile.am

@ -1,7 +1,8 @@
ACLOCAL_AMFLAGS = -I m4
AUTOMAKE_OPTIONS = subdir-objects
AM_CFLAGS += -I../../include/
AM_CFLAGS += -I../../include/ -std=c99 -DREENTRANT -lpthread
AM_LDFLAGS += -lpthread
CB = cbuf.c read.c \
get_line.c set_data.c get_data.c \
@ -14,3 +15,4 @@ noinst_LTLIBRARIES = libcbuf.la
libcbuf_la_SOURCES = $(CB)
libcbuf_la_CFLAGS = $(AM_CFLAGS)
libcbuf_la_LIBADD = $(AM_LDFLAGS)

4
src/hash/Makefile.am

@ -1,7 +1,8 @@
ACLOCAL_AMFLAGS = -I m4
AUTOMAKE_OPTIONS = subdir-objects
AM_CFLAGS += -I../../include/
AM_CFLAGS += -I../../include/ -std=c99 -DREENTRANT -lpthread
AM_LDFLAGS += -lpthread
HASH = hash.c add.c get.c get_first.c delete.c each.c value.c \
cleanup.c interface/hashable.c
@ -10,3 +11,4 @@ noinst_LTLIBRARIES = libhash.la
libhash_la_SOURCES = $(HASH)
libhash_la_CFLAGS = $(AM_CFLAGS)
libhash_la_LIBADD = $(AM_LDFLAGS)

2
src/hash/add.c

@ -48,7 +48,7 @@ hashAddComp(const void * a, const void * b)
void *
TR_hashAdd(TR_Hash this, void * operand)
{
void * found = TR_treeInsert(&this->root, operand, hashAddComp);
void * found = TR_treeInsert(this->tree, operand, hashAddComp);
if (NULL == found) {
return NULL;

6
src/hash/cleanup.c

@ -36,10 +36,12 @@ void
TR_hashCleanup(TR_Hash this)
{
if (this->cleanup_no_free) {
TR_treeDestroy(&(this->root), NULL);
TR_treeDestroy(this->tree, NULL);
} else {
TR_treeDestroy(&(this->root), tDelete);
TR_treeDestroy(this->tree, tDelete);
}
TR_delete(this->tree);
}
// vim: set ts=4 sw=4:

4
src/hash/delete.c

@ -51,7 +51,7 @@ TR_hashDelete(TR_Hash this, const char * search, size_t nsearch)
unsigned long hash = TR_sdbm((const unsigned char *)search, nsearch);
void * found = NULL;
found = TR_treeDelete(&(this->root), &hash, hashDeleteComp);
found = TR_treeDelete(this->tree, &hash, hashDeleteComp);
return found;
}
@ -59,7 +59,7 @@ TR_hashDelete(TR_Hash this, const char * search, size_t nsearch)
void *
TR_hashDeleteByVal(TR_Hash this, unsigned long hash)
{
void * found = TR_treeDelete(&(this->root), &hash, hashDeleteComp);
void * found = TR_treeDelete(this->tree, &hash, hashDeleteComp);
return found;
}

4
src/hash/each.c

@ -34,7 +34,7 @@ walk(const void * node, const void * data, const int depth)
cb(node, data);
}
void
unsigned long
TR_hashEach(
TR_Hash this,
const void * data,
@ -42,7 +42,7 @@ TR_hashEach(
{
cb = callback;
TR_treeWalk(this->root, data, walk);
return TR_treeWalk(this->tree, data, walk);
}
// vim: set ts=4 sw=4:

4
src/hash/get.c

@ -52,7 +52,7 @@ void *
TR_hashGet(TR_Hash this, const char * search, size_t nsearch)
{
unsigned long hash = TR_sdbm((const unsigned char *)search, nsearch);
void * found = TR_treeFind(this->root, &hash, hashGetComp);
void * found = TR_treeFind(this->tree, &hash, hashGetComp);
return found;
}
@ -60,7 +60,7 @@ TR_hashGet(TR_Hash this, const char * search, size_t nsearch)
void *
TR_hashGetByVal(TR_Hash this, unsigned long hash)
{
void * found = TR_treeFind(this->root, &hash, hashGetComp);
void * found = TR_treeFind(this->tree, &hash, hashGetComp);
return found;
}

2
src/hash/get_first.c

@ -27,7 +27,7 @@
void *
TR_hashGetFirst(TR_Hash this)
{
return this->root;
return this->tree->root;
}
// vim: set ts=4 sw=4:

6
src/hash/hash.c

@ -31,6 +31,10 @@ static
int
hashCtor(void * _this, va_list * params)
{
TR_Hash this = _this;
this->tree = TR_new(TR_Tree);
return 0;
}
@ -41,6 +45,8 @@ hashDtor(void * _this)
TR_Hash this = _this;
TR_hashCleanup(this);
TR_delete(this->tree);
}
TR_INIT_IFACE(TR_Class, hashCtor, hashDtor, NULL);

16
src/queue/Makefile.am

@ -1,17 +1,13 @@
ACLOCAL_AMFLAGS = -I m4
AUTOMAKE_OPTIONS = subdir-objects
AM_CFLAGS += -I../../include/
AM_CFLAGS += -I../../include/ -std=c99 -DREENTRANT -lpthread
AM_LDFLAGS += -lpthread
noinst_LTLIBRARIES = libqueue.la
QUEUE = queue.c get.c put.c put_first.c find.c find_parent.c delete.c destroy.c
libqueue_la_SOURCES = queue.c \
get.c \
put.c \
put_first.c \
find.c \
find_parent.c \
delete.c \
destroy.c
noinst_LTLIBRARIES = libqueue.la
libqueue_la_SOURCES = $(QUEUE)
libqueue_la_CFLAGS = $(AM_CFLAGS)
libqueue_la_LIBADD = $(AM_LDFLAGS)

8
src/queue/delete.c

@ -26,9 +26,13 @@
void
TR_queueDelete(TR_Queue this, void * msg)
{
TR_Queue node, parent = TR_queueFindParent(this, msg);
TR_Queue node, parent;
if (! parent) return;
parent = TR_queueFindParent(this, msg);
if (! parent) {
return;
}
node = parent->next;
parent->next = node->next;

4
src/queue/destroy.c

@ -28,7 +28,9 @@
void
TR_queueDestroy(TR_Queue this)
{
TR_Queue node = this->first;
TR_Queue node;
node = this->first;
while (NULL != node) {
TR_Queue next = node->next;

4
src/queue/put.c

@ -26,7 +26,9 @@
void
TR_queuePut(TR_Queue this, void * msg)
{
TR_Queue node = (this->last)? this->last : this;
TR_Queue node;
node = (this->last)? this->last : this;
node->next = TR_new(TR_Queue);
this->last = node->next;

4
src/queue/put_first.c

@ -26,7 +26,9 @@
void
TR_queuePutFirst(TR_Queue this, void * msg)
{
TR_Queue current_first = this->first;
TR_Queue current_first;
current_first = this->first;
this->first = this->next = TR_new(TR_Queue);
this->first->next = current_first;

4
src/queue/queue.c

@ -40,7 +40,9 @@ static
void
queueDtor(void * _this)
{
TR_queueDestroy((TR_Queue)_this);
TR_Queue this = _this;
TR_queueDestroy(this);
}
TR_INIT_IFACE(TR_Class, queueCtor, queueDtor, NULL);

7
src/tree/Makefile.am

@ -1,16 +1,19 @@
ACLOCAL_AMFLAGS = -I m4
AUTOMAKE_OPTIONS = subdir-objects
AM_CFLAGS += -I../../include/ -std=c99 -DREENTRANT -lpthread
AM_LDFLAGS += -lpthread
TREE = tree.c \
tree_node.c \
find.c \
insert.c \
delete.c \
walk.c \
destroy.c
AM_CFLAGS += -I../../include/
noinst_LTLIBRARIES = libtree.la
libtree_la_SOURCES = $(TREE)
libtree_la_CFLAGS = $(AM_CFLAGS)
libtree_la_LIBADD = $(AM_LDFLAGS)

20
src/tree/delete.c

@ -24,15 +24,16 @@
#include "tr/tree.h"
void *
TR_treeDelete(TR_Tree * this, const void * search, TR_TreeComp comp)
TR_treeDelete(TR_Tree this, const void * search, TR_TreeComp comp)
{
TR_Tree node = *this;
TR_Tree del_node;
TR_Tree sibling;
TR_TreeNode node;
TR_TreeNode del_node;
TR_TreeNode sibling;
int found;
void * data;
node = this->root;
TR_TREE_FIND(node, search, found, comp);
/*
@ -57,7 +58,7 @@ TR_treeDelete(TR_Tree * this, const void * search, TR_TreeComp comp)
* out inOrderSuccessor and remove the inOrderSuccessor.
*/
if (NULL != TR_TREE_LEFT(node) && NULL != TR_TREE_RIGHT(node)) {
TR_Tree successor;
TR_TreeNode successor;
TR_TREE_INORDER_SUCC(node, successor);
@ -66,12 +67,12 @@ TR_treeDelete(TR_Tree * this, const void * search, TR_TreeComp comp)
}
{
TR_Tree child = TR_TREE_CHILD(node);
TR_TreeNode child = TR_TREE_CHILD(node);
/*
* if we still have one child replace ourself with it.
*/
TR_TREE_REPLACE_NODE(this, node, child);
TR_TREE_REPLACE_NODE(&(this->root), node, child);
/*
* and finally delete the node...and prepare ourselfs
@ -105,9 +106,10 @@ TR_treeDelete(TR_Tree * this, const void * search, TR_TreeComp comp)
* rebalancing process...(this does not make much sense, but
* to be honest I don't know now.)
*/
TR_TREE_BALANCE_DELETE(this, node, sibling);
TR_TREE_BALANCE_DELETE(&(this->root), node, sibling);
TR_delete(del_node);
return data;
}

13
src/tree/destroy.c

@ -24,12 +24,15 @@
#include "tr/tree.h"
void
TR_treeDestroy(TR_Tree * this, TR_TreeAction action)
TR_treeDestroy(TR_Tree this, TR_TreeAction action)
{
TR_Tree previous = * this;
TR_Tree node = * this;
TR_TreeNode previous;
TR_TreeNode node;
int depth = 1;
previous = this->root;
node = this->root;
/*
* I think this has something like O(n+log(n)) on a ballanced
* tree because I have to traverse back the rightmost leaf to
@ -44,7 +47,7 @@ TR_treeDestroy(TR_Tree * this, TR_TreeAction action)
|| previous == TR_TREE_LEFT(node)) && NULL == TR_TREE_RIGHT(node))
|| previous == TR_TREE_RIGHT(node)) {
TR_Tree parent = TR_TREE_PARENT(node);
TR_TreeNode parent = TR_TREE_PARENT(node);
if (action) {
action(node->data, NULL, depth);
@ -82,7 +85,7 @@ TR_treeDestroy(TR_Tree * this, TR_TreeAction action)
}
}
*this = NULL;
this->root = NULL;
}
// vim: set ts=4 sw=4:

8
src/tree/find.c

@ -26,10 +26,14 @@ void *
TR_treeFind(TR_Tree this, const void * search, TR_TreeComp comp)
{
int found;
TR_TreeNode node;
void * retval;
TR_TREE_FIND(this, search, found, comp);
node = this->root;
TR_TREE_FIND(node, search, found, comp);
retval = found == 0 ? node->data : NULL;
return found == 0 ? this->data : NULL;
return retval;
}
// vim: set ts=4 sw=4:

20
src/tree/insert.c

@ -24,11 +24,14 @@
#include "tr/tree.h"
void *
TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp)
TR_treeInsert(TR_Tree this, const void * search, TR_TreeComp comp)
{
TR_Tree node = *this;
TR_Tree new_node = NULL;
TR_TreeNode new_node = NULL;
TR_TreeNode node;
int found;
void * retval;
node = this->root;
/*
* insert the node or return the one in tree if comparison
@ -39,7 +42,7 @@ TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp)
* if the root is NULL we simple add the element and set
* node to it.
*/
*this = node = new_node = TR_new(TR_Tree, search);
this->root = node = new_node = TR_new(TR_TreeNode, search);
} else {
TR_TREE_FIND(node, search, found, comp);
@ -55,11 +58,11 @@ TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp)
} else {
// not found
if (0 < found) {
node->left = TR_new(TR_Tree, search);
node->left = TR_new(TR_TreeNode, search);
node->left->parent = node;
node = new_node = node->left;
} else {
node->right = TR_new(TR_Tree, search);
node->right = TR_new(TR_TreeNode, search);
node->right->parent = node;
node = new_node = node->right;
}
@ -70,9 +73,10 @@ TR_treeInsert(TR_Tree * this, const void * search, TR_TreeComp comp)
* we expect node not to be NULL and pointing to our
* new node at this point...now rabalance the tree
*/
TR_TREE_BALANCE_INSERT(this, node);
TR_TREE_BALANCE_INSERT(&(this->root), node);
retval = new_node->data;
return new_node->data;
return retval;
}
// vim: set ts=4 sw=4:

6
src/tree/tree.c

@ -33,11 +33,7 @@ treeCtor(void * _this, va_list * params)
{
TR_Tree this = _this;
this->data = va_arg(*params, void *);
this->color = rbRed;
this->parent = NULL;
this->left = NULL;
this->right = NULL;
this->root = NULL;
return 0;
}

50
src/tree/tree_node.c

@ -0,0 +1,50 @@
/**
* \file
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2014 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _GNU_SOURCE
#include <stdarg.h>
#include "trbase.h"
#include "tr/tree.h"
static
int
treeNodeCtor(void * _this, va_list * params)
{
TR_TreeNode this = _this;
this->data = va_arg(*params, void *);
this->color = rbRed;
this->parent = NULL;
this->left = NULL;
this->right = NULL;
return 0;
}
static void treeNodeDtor(void * _this) {}
TR_INIT_IFACE(TR_Class, treeNodeCtor, treeNodeDtor, NULL);
TR_CREATE_CLASS(TR_TreeNode, NULL, NULL, TR_IF(TR_Class));
// vim: set ts=4 sw=4:

13
src/tree/walk.c

@ -22,12 +22,16 @@
#include "tr/tree.h"
void
unsigned long
TR_treeWalk(TR_Tree this, const void * data, TR_TreeAction action)
{
TR_Tree previous = this;
TR_Tree node = this;
TR_TreeNode previous;
TR_TreeNode node;
int depth = 1;
unsigned long processed = 0;
previous = this->root;
node = this->root;
while (NULL != node) {
if (previous == TR_TREE_RIGHT(node)) {
@ -40,6 +44,7 @@ TR_treeWalk(TR_Tree this, const void * data, TR_TreeAction action)
if (NULL == TR_TREE_LEFT(node) || previous == TR_TREE_LEFT(node)) {
if (action) {
action(node->data, data, depth);
processed++;
}
previous = node;
@ -56,6 +61,8 @@ TR_treeWalk(TR_Tree this, const void * data, TR_TreeAction action)
depth++;
}
}
return processed;
}
// vim: set ts=4 sw=4:
Loading…
Cancel
Save