added mempool allocator

Mon, 15 Jul 2013 16:59:52 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Mon, 15 Jul 2013 16:59:52 +0200
changeset 113
8693d7874773
parent 112
6384016df2a3
child 114
5a0859739b76

added mempool allocator

test/main.c file | annotate | diff | comparison | revisions
test/mpool_tests.c file | annotate | diff | comparison | revisions
test/mpool_tests.h file | annotate | diff | comparison | revisions
ucx/mempool.c file | annotate | diff | comparison | revisions
ucx/mempool.h file | annotate | diff | comparison | revisions
--- a/test/main.c	Mon Jul 15 15:43:18 2013 +0200
+++ b/test/main.c	Mon Jul 15 16:59:52 2013 +0200
@@ -153,6 +153,7 @@
         ucx_test_register(suite, test_ucx_mempool_malloc);
         ucx_test_register(suite, test_ucx_mempool_malloc_with_chcap);
         ucx_test_register(suite, test_ucx_mempool_calloc);
+        ucx_test_register(suite, test_ucx_mempool_free);
         ucx_test_register(suite, test_ucx_mempool_set_destr);
         ucx_test_register(suite, test_ucx_mempool_reg_destr);
         ucx_test_register(suite, test_ucx_mempool_realloc);
--- a/test/mpool_tests.c	Mon Jul 15 15:43:18 2013 +0200
+++ b/test/mpool_tests.c	Mon Jul 15 16:59:52 2013 +0200
@@ -37,7 +37,7 @@
     UCX_TEST_ASSERT(pool->ndata == 0, "uninitialized counter");
     UCX_TEST_ASSERT(pool->data != NULL, "no memory addressed");
     UCX_TEST_END
-    ucx_mempool_free(pool);
+    ucx_mempool_destroy(pool);
 }
 
 UCX_TEST_IMPLEMENT(test_ucx_mempool_malloc) {
@@ -56,7 +56,7 @@
     UCX_TEST_ASSERT(*test == 5, "wrong pointer");
     
     UCX_TEST_END
-    ucx_mempool_free(pool);
+    ucx_mempool_destroy(pool);
 }
 
 UCX_TEST_IMPLEMENT(test_ucx_mempool_malloc_with_chcap) {
@@ -76,7 +76,7 @@
     UCX_TEST_ASSERT(*test == 5, "wrong pointer");
     
     UCX_TEST_END
-    ucx_mempool_free(pool);
+    ucx_mempool_destroy(pool);
 }
 
 UCX_TEST_IMPLEMENT(test_ucx_mempool_calloc) {
@@ -90,7 +90,37 @@
     UCX_TEST_ASSERT(test[0] == 0 && test[1] == 0, "failed");
     
     UCX_TEST_END
-    ucx_mempool_free(pool);
+    ucx_mempool_destroy(pool);
+}
+
+UCX_TEST_IMPLEMENT(test_ucx_mempool_free) {
+    UcxMempool *pool = ucx_mempool_new(16);
+    void *mem1;
+    void *mem2;
+    
+    UCX_TEST_BEGIN
+    
+    mem1 = ucx_mempool_malloc(pool, 16);
+    ucx_mempool_free(pool, mem1);
+    
+    UCX_TEST_ASSERT(pool->ndata == 0, "mempool not empty");
+    
+    ucx_mempool_malloc(pool, 16);
+    ucx_mempool_malloc(pool, 16);
+    mem1 = ucx_mempool_malloc(pool, 16);
+    ucx_mempool_malloc(pool, 16);
+    mem2 = ucx_mempool_malloc(pool, 16);
+    
+    ucx_mempool_free(pool, mem1);
+    
+    UCX_TEST_ASSERT(pool->ndata == 4, "wrong mempool size");
+    
+    ucx_mempool_free(pool, mem2);
+    
+    UCX_TEST_ASSERT(pool->ndata == 3, "wrong mempool size");
+    
+    UCX_TEST_END
+    ucx_mempool_destroy(pool);
 }
 
 void test_setdestr(void* elem) {
@@ -118,7 +148,7 @@
     UCX_TEST_ASSERT(
             test[0] == 5 && test[1] == (intptr_t) cb, "setdestr destroyed data")
     
-    ucx_mempool_free(pool);
+    ucx_mempool_destroy(pool);
     
     UCX_TEST_ASSERT(*cb == 42, "destructor not called");
     
@@ -146,7 +176,7 @@
     
     UCX_TEST_ASSERT(*pooladdr == test_setdestr, "failed");
     
-    ucx_mempool_free(pool);
+    ucx_mempool_destroy(pool);
     UCX_TEST_ASSERT(*cb == 42, "destructor not called");
     UCX_TEST_END
 
@@ -183,7 +213,7 @@
     UCX_TEST_ASSERT(
             test[0] == 5 && test[1] == (intptr_t) cb, "realloc destroyed data")
     
-    ucx_mempool_free(pool);
+    ucx_mempool_destroy(pool);
     
     UCX_TEST_ASSERT(*cb == 42, "destructor not called");
     
--- a/test/mpool_tests.h	Mon Jul 15 15:43:18 2013 +0200
+++ b/test/mpool_tests.h	Mon Jul 15 16:59:52 2013 +0200
@@ -40,6 +40,7 @@
 UCX_TEST_DECLARE(test_ucx_mempool_malloc);
 UCX_TEST_DECLARE(test_ucx_mempool_malloc_with_chcap);
 UCX_TEST_DECLARE(test_ucx_mempool_calloc);
+UCX_TEST_DECLARE(test_ucx_mempool_free);
 UCX_TEST_DECLARE(test_ucx_mempool_set_destr);
 UCX_TEST_DECLARE(test_ucx_mempool_reg_destr);
 UCX_TEST_DECLARE(test_ucx_mempool_realloc);
--- a/ucx/mempool.c	Mon Jul 15 15:43:18 2013 +0200
+++ b/ucx/mempool.c	Mon Jul 15 16:59:52 2013 +0200
@@ -112,7 +112,7 @@
                 return newm + sizeof(ucx_destructor);
             }
         }
-        fprintf(stderr, "FATAL: 0x%08" PRIxPTR" not in mpool 0x%08" PRIxPTR"\n",
+        fprintf(stderr, "FATAL: 0x%08"PRIxPTR" not in mpool 0x%08" PRIxPTR"\n",
           (intptr_t)ptr, (intptr_t)pool);
         exit(1);
     } else {
@@ -120,14 +120,37 @@
     }
 }
 
-void ucx_mempool_free(UcxMempool *pool) {
+void ucx_mempool_free(UcxMempool *pool, void *ptr) {
+    ucx_memchunk *chunk = (ucx_memchunk*)((char*)ptr-sizeof(ucx_destructor));
+    for(size_t i=0 ; i<pool->ndata ; i++) {
+        if(chunk == pool->data[i]) {
+            if(chunk->destructor != NULL) {
+                chunk->destructor(&chunk->c);
+            }
+            free(chunk);
+            size_t last_index = pool->ndata - 1;
+            if(i != last_index) {
+                pool->data[i] = pool->data[last_index];
+            }
+            pool->ndata--;
+            return;
+        }
+    }
+    fprintf(stderr, "FATAL: 0x%08"PRIxPTR" not in mpool 0x%08" PRIxPTR"\n",
+            (intptr_t)ptr, (intptr_t)pool);
+    exit(1);
+}
+
+void ucx_mempool_destroy(UcxMempool *pool) {
     ucx_memchunk *chunk;
     for(size_t i=0 ; i<pool->ndata ; i++) {
         chunk = (ucx_memchunk*) pool->data[i];
-        if(chunk->destructor != NULL) {
-            chunk->destructor(&chunk->c);
+        if(chunk) {
+            if(chunk->destructor != NULL) {
+                chunk->destructor(&chunk->c);
+            }
+            free(chunk);
         }
-        free(chunk);
     }
     free(pool->data);
     free(pool);
@@ -145,3 +168,17 @@
     rd->ptr = ptr;
     ucx_mempool_set_destr(rd, ucx_mempool_shared_destr);
 }
+
+UcxAllocator* ucx_mempool_allocator(UcxMempool *pool) {
+    UcxAllocator *allocator = (UcxAllocator*)ucx_mempool_malloc(
+            pool, sizeof(UcxAllocator));
+    if(!allocator) {
+        return NULL;
+    }
+    allocator->malloc = (ucx_allocator_malloc)ucx_mempool_malloc;
+    allocator->calloc = (ucx_allocator_calloc)ucx_mempool_calloc;
+    allocator->realloc = (ucx_allocator_realloc)ucx_mempool_realloc;
+    allocator->free = (ucx_allocator_free)ucx_mempool_free;
+    allocator->pool = pool;
+    return allocator;
+}
--- a/ucx/mempool.h	Mon Jul 15 15:43:18 2013 +0200
+++ b/ucx/mempool.h	Mon Jul 15 16:59:52 2013 +0200
@@ -45,10 +45,6 @@
     size_t size;
 } UcxMempool;
 
-#define UCX_ALLOCATOR_MEMPOOL(pool) {pool, \
-    (ucx_allocator_malloc) ucx_mempool_malloc, \
-    (ucx_allocator_calloc) ucx_mempool_calloc, \
-    (ucx_allocator_realloc) ucx_mempool_realloc}
 
 #define ucx_mempool_new_default() ucx_mempool_new(16)
 UcxMempool *ucx_mempool_new(size_t n);
@@ -57,12 +53,14 @@
 void *ucx_mempool_malloc(UcxMempool *pool, size_t n);
 void *ucx_mempool_calloc(UcxMempool *pool, size_t nelem, size_t elsize);
 void *ucx_mempool_realloc(UcxMempool *pool, void *ptr, size_t n);
+void ucx_mempool_free(UcxMempool *pool, void *ptr);
 
-void ucx_mempool_free(UcxMempool *pool);
+void ucx_mempool_destroy(UcxMempool *pool);
 
 void ucx_mempool_set_destr(void *ptr, ucx_destructor func);
 void ucx_mempool_reg_destr(UcxMempool *pool, void *ptr, ucx_destructor destr);
 
+UcxAllocator* ucx_mempool_allocator(UcxMempool *pool);
 
 #ifdef	__cplusplus
 }

mercurial