From a8ae30c3c4abdd5e0193f36522c7a6bd9804cc16 Mon Sep 17 00:00:00 2001 From: Jonathan Schleifer Date: Sun, 22 Apr 2012 15:09:52 +0200 Subject: [PATCH] Add refpool. --- src/Makefile | 11 ++--- src/object.c | 35 ++++++++++++++++ src/object.h | 1 + src/refpool.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/refpool.h | 36 +++++++++++++++++ tests/tests.c | 57 +++++++++++++------------- 6 files changed, 216 insertions(+), 33 deletions(-) create mode 100644 src/refpool.c create mode 100644 src/refpool.h diff --git a/src/Makefile b/src/Makefile index d09f54e..d378f47 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,11 +2,12 @@ SHARED_LIB = ${LIB_PREFIX}corefw${LIB_SUFFIX} LIB_MAJOR = 0 LIB_MINOR = 0 -SRCS = array.c \ - class.c \ - map.c \ - object.c \ - range.c \ +SRCS = array.c \ + class.c \ + map.c \ + object.c \ + range.c \ + refpool.c \ string.c INCLUDES = ${SRCS:.c=.h} \ diff --git a/src/object.c b/src/object.c index bc53a50..777fd27 100644 --- a/src/object.c +++ b/src/object.c @@ -25,8 +25,10 @@ */ #include +#include #include "object.h" +#include "refpool.h" void* cfw_new(CFWClass *class, ...) @@ -54,6 +56,39 @@ cfw_new(CFWClass *class, ...) return obj; } +void* +cfw_new_p(CFWClass *class, ...) +{ + CFWObject *obj; + + assert(class != cfw_refpool); + + if ((obj = malloc(class->size)) == NULL) + return NULL; + + obj->cls = class; + obj->ref_cnt = 1; + + if (class->ctor != NULL) { + va_list args; + va_start(args, class); + + if (!class->ctor(obj, args)) { + cfw_unref(obj); + return NULL; + } + + va_end(args); + } + + if (!cfw_refpool_add(obj)) { + cfw_unref(obj); + return NULL; + } + + return obj; +} + void* cfw_ref(void *ptr) { diff --git a/src/object.h b/src/object.h index c5bdac3..5afdc42 100644 --- a/src/object.h +++ b/src/object.h @@ -36,6 +36,7 @@ typedef struct CFWObject { extern CFWClass *cfw_object; extern void* cfw_new(CFWClass*, ...); +extern void* cfw_new_p(CFWClass*, ...); extern void* cfw_ref(void*); extern void cfw_unref(void*); extern void cfw_free(void*); diff --git a/src/refpool.c b/src/refpool.c new file mode 100644 index 0000000..63d28fa --- /dev/null +++ b/src/refpool.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2012, Jonathan Schleifer + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "object.h" +#include "refpool.h" +#include "array.h" + +struct CFWRefPool { + CFWObject obj; + void **data; + size_t size; + CFWRefPool *prev, *next; +}; + +static CFWRefPool *top; + +static bool +ctor(void *ptr, va_list args) +{ + CFWRefPool *pool = ptr; + + pool->data = NULL; + pool->size = 0; + + if (top != NULL) { + pool->prev = top; + top->next = pool; + } else + pool->prev = NULL; + pool->next = NULL; + + top = pool; + + return true; +} + +static void +dtor(void *ptr) +{ + CFWRefPool *pool = ptr; + size_t i; + + if (pool->next != NULL) + cfw_unref(pool->next); + + for (i = 0; i < pool->size; i++) + cfw_unref(pool->data[i]); + + if (pool->data != NULL) + free(pool->data); + + top = pool->prev; +} + +bool +cfw_refpool_add(void *ptr) +{ + void **ndata; + + assert(top != NULL); + + if (top->data != NULL) + ndata = realloc(top->data, (top->size + 1) * sizeof(void*)); + else + ndata = malloc((top->size + 1) * sizeof(void*)); + + if (ndata == NULL) + return false; + + ndata[top->size++] = ptr; + + top->data = ndata; + + return true; +} + +static CFWClass class = { + .name = "CFWRefPool", + .size = sizeof(CFWRefPool), + .ctor = ctor, + .dtor = dtor +}; +CFWClass *cfw_refpool = &class; diff --git a/src/refpool.h b/src/refpool.h new file mode 100644 index 0000000..0b57336 --- /dev/null +++ b/src/refpool.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2012, Jonathan Schleifer + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __COREFW_REFPOOL_H__ +#define __COREFW_REFPOOL_H__ + +#include "class.h" + +typedef struct CFWRefPool CFWRefPool; +extern CFWClass *cfw_refpool; +extern bool cfw_refpool_add(void*); + +#endif diff --git a/tests/tests.c b/tests/tests.c index 4aa89a9..6b9d626 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -27,11 +27,12 @@ #include #include "object.h" +#include "refpool.h" #include "string.h" #include "array.h" #include "map.h" -void +static void print_map(CFWMap *map) { cfw_map_iter_t iter; @@ -57,55 +58,55 @@ print_map(CFWMap *map) int main() { - CFWString *s[3]; + CFWRefPool *p; CFWArray *a; + CFWString *s, *s2; CFWMap *m; size_t i; - s[0] = cfw_new(cfw_string, "Hallo"); - s[1] = cfw_new(cfw_string, " Welt"); - s[2] = cfw_new(cfw_string, "!"); + p = cfw_new(cfw_refpool); - a = cfw_new(cfw_array, s[0], s[1], s[2], NULL); + a = cfw_new_p(cfw_array, + cfw_new_p(cfw_string, "Hallo"), + cfw_new_p(cfw_string, " Welt"), + cfw_new_p(cfw_string, "!"), NULL); - cfw_unref(s[0]); - cfw_unref(s[1]); - cfw_unref(s[2]); - - s[0] = cfw_new(cfw_string, NULL); + s = cfw_new(cfw_string, NULL); for (i = 0; i < cfw_array_size(a); i++) - cfw_string_append(s[0], cfw_array_get(a, i)); + cfw_string_append(s, cfw_array_get(a, i)); - cfw_unref(a); + cfw_unref(p); - puts(cfw_string_c(s[0])); + puts(cfw_string_c(s)); - s[1] = cfw_new(cfw_string, "ll"); - printf("%zd\n", cfw_string_find(s[0], s[1], cfw_range_all)); - cfw_unref(s[1]); + p = cfw_new(cfw_refpool); + s2 = cfw_new_p(cfw_string, "ll"); + printf("%zd\n", cfw_string_find(s, s2, cfw_range_all)); - cfw_unref(s[0]); + cfw_unref(p); + cfw_unref(s); - s[0] = cfw_new(cfw_string, "Hallo"); - s[1] = cfw_new(cfw_string, "Welt!"); + p = cfw_new(cfw_refpool); - m = cfw_new(cfw_map, s[0], s[1], NULL); - cfw_unref(s[1]); + m = cfw_new_p(cfw_map, + cfw_new_p(cfw_string, "Hallo"), + cfw_new_p(cfw_string, "Welt!"), + cfw_new_p(cfw_string, "Test"), + cfw_new_p(cfw_string, "success!"), NULL); print_map(m); - s[1] = cfw_new(cfw_string, "Test"); - cfw_map_set(m, s[0], s[1]); - cfw_unref(s[1]); + cfw_map_set(m, + cfw_new_p(cfw_string, "Hallo"), + cfw_new_p(cfw_string, "Test")); print_map(m); - cfw_map_set(m, s[0], NULL); + cfw_map_set(m, cfw_new_p(cfw_string, "Hallo"), NULL); print_map(m); - cfw_unref(s[0]); - cfw_unref(m); + cfw_unref(p); return 0; }