X-Git-Url: https://develop.uap-core.de/gitweb/uwplayer.git/blobdiff_plain/67b35790d6ab8581c96b3182e63eb2c0ffab5123..01d5015ba093f8c5fdb18b669943c7da6450e72f:/ucx/mempool.c diff --git a/ucx/mempool.c b/ucx/mempool.c index beedc31..7b8d3a7 100644 --- a/ucx/mempool.c +++ b/ucx/mempool.c @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2017 Mike Becker, Olaf Wintermann All rights reserved. + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -26,212 +26,207 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "ucx/mempool.h" - -#include +#include "cx/mempool.h" +#include "cx/utils.h" #include -#include -#ifdef __cplusplus -#define __STDC_FORMAT_MACROS -#endif -#include - -/** Capsule for destructible memory chunks. */ -typedef struct { - /** The destructor for the memory chunk. */ - ucx_destructor destructor; - /** - * First byte of the memory chunk. - * Note, that the address &c is also the address - * of the whole memory chunk. - */ - char c; -} ucx_memchunk; - -/** Capsule for data and its destructor. */ -typedef struct { - /** The destructor for the data. */ - ucx_destructor destructor; - /** A pointer to the data. */ - void *ptr; -} ucx_regdestr; - -#ifdef __cplusplus -extern "C" -#endif -void ucx_mempool_shared_destr(void* ptr) { - ucx_regdestr *rd = (ucx_regdestr*)ptr; - rd->destructor(rd->ptr); -} -UcxMempool *ucx_mempool_new(size_t n) { - size_t poolsz; - if(ucx_szmul(n, sizeof(void*), &poolsz)) { - return NULL; - } - - UcxMempool *pool = (UcxMempool*)malloc(sizeof(UcxMempool)); - if (!pool) { - return NULL; - } - - pool->data = (void**) malloc(poolsz); - if (pool->data == NULL) { - free(pool); - return NULL; - } - - pool->ndata = 0; - pool->size = n; - - UcxAllocator *allocator = (UcxAllocator*)malloc(sizeof(UcxAllocator)); - if(!allocator) { - free(pool->data); - free(pool); - 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; - pool->allocator = allocator; - - return pool; -} - -int ucx_mempool_chcap(UcxMempool *pool, size_t newcap) { - if (newcap < pool->ndata) { - return 1; - } - - size_t newcapsz; - if(ucx_szmul(newcap, sizeof(void*), &newcapsz)) { - return 1; - } - - void **data = (void**) realloc(pool->data, newcapsz); - if (data) { - pool->data = data; - pool->size = newcap; - return 0; - } else { - return 1; - } -} - -void *ucx_mempool_malloc(UcxMempool *pool, size_t n) { - if(((size_t)-1) - sizeof(ucx_destructor) < n) { - return NULL; - } - - if (pool->ndata >= pool->size) { - size_t newcap = pool->size*2; - if (newcap < pool->size || ucx_mempool_chcap(pool, newcap)) { +struct cx_mempool_memory_s { + /** The destructor. */ + cx_destructor_func destructor; + /** The actual memory. */ + char c[]; +}; + +static void *cx_mempool_malloc( + void *p, + size_t n +) { + struct cx_mempool_s *pool = p; + + if (pool->size >= pool->capacity) { + size_t newcap = pool->capacity - (pool->capacity % 16) + 16; + struct cx_mempool_memory_s **newdata = realloc(pool->data, newcap*sizeof(struct cx_mempool_memory_s*)); + if (newdata == NULL) { return NULL; } + pool->data = newdata; + pool->capacity = newcap; } - void *p = malloc(sizeof(ucx_destructor) + n); - ucx_memchunk *mem = (ucx_memchunk*)p; - if (!mem) { + struct cx_mempool_memory_s *mem = malloc(sizeof(cx_destructor_func) + n); + if (mem == NULL) { return NULL; } - mem->destructor = NULL; - pool->data[pool->ndata] = mem; - pool->ndata++; + mem->destructor = pool->auto_destr; + pool->data[pool->size] = mem; + pool->size++; - return &(mem->c); + return mem->c; } -void *ucx_mempool_calloc(UcxMempool *pool, size_t nelem, size_t elsize) { +static void *cx_mempool_calloc( + void *p, + size_t nelem, + size_t elsize +) { size_t msz; - if(ucx_szmul(nelem, elsize, &msz)) { + if (cx_szmul(nelem, elsize, &msz)) { return NULL; } - - void *ptr = ucx_mempool_malloc(pool, msz); - if (!ptr) { + void *ptr = cx_mempool_malloc(p, msz); + if (ptr == NULL) { return NULL; } memset(ptr, 0, nelem * elsize); return ptr; } -void *ucx_mempool_realloc(UcxMempool *pool, void *ptr, size_t n) { - if(((size_t)-1) - sizeof(ucx_destructor) < n) { - return NULL; - } - - char *mem = ((char*)ptr) - sizeof(ucx_destructor); - char *newm = (char*) realloc(mem, n + sizeof(ucx_destructor)); - if (!newm) { +static void *cx_mempool_realloc( + void *p, + void *ptr, + size_t n +) { + struct cx_mempool_s *pool = p; + + struct cx_mempool_memory_s *mem, *newm; + mem = (struct cx_mempool_memory_s*)(((char *) ptr) - sizeof(cx_destructor_func)); + newm = realloc(mem, n + sizeof(cx_destructor_func)); + + if (newm == NULL) { return NULL; } if (mem != newm) { - for(size_t i=0 ; i < pool->ndata ; i++) { - if(pool->data[i] == mem) { + cx_for_n(i, pool->size) { + if (pool->data[i] == mem) { pool->data[i] = newm; - return newm + sizeof(ucx_destructor); + return ((char*)newm) + sizeof(cx_destructor_func); } } - fprintf(stderr, "FATAL: 0x%08" PRIxPTR" not in mpool 0x%08" PRIxPTR"\n", - (intptr_t)ptr, (intptr_t)pool); abort(); } else { - return newm + sizeof(ucx_destructor); + return ptr; } } -void ucx_mempool_free(UcxMempool *pool, void *ptr) { - ucx_memchunk *chunk = (ucx_memchunk*)((char*)ptr-sizeof(ucx_destructor)); - for(size_t i=0 ; indata ; i++) { - if(chunk == pool->data[i]) { - if(chunk->destructor != NULL) { - chunk->destructor(&(chunk->c)); +static void cx_mempool_free( + void *p, + void *ptr +) { + struct cx_mempool_s *pool = p; + + struct cx_mempool_memory_s *mem = (struct cx_mempool_memory_s *) + ((char *) ptr - sizeof(cx_destructor_func)); + + cx_for_n(i, pool->size) { + if (mem == pool->data[i]) { + if (mem->destructor) { + mem->destructor(mem->c); } - free(chunk); - size_t last_index = pool->ndata - 1; - if(i != last_index) { + free(mem); + size_t last_index = pool->size - 1; + if (i != last_index) { pool->data[i] = pool->data[last_index]; pool->data[last_index] = NULL; } - pool->ndata--; + pool->size--; return; } } - fprintf(stderr, "FATAL: 0x%08" PRIxPTR" not in mpool 0x%08" PRIxPTR"\n", - (intptr_t)ptr, (intptr_t)pool); abort(); } -void ucx_mempool_destroy(UcxMempool *pool) { - ucx_memchunk *chunk; - for(size_t i=0 ; indata ; i++) { - chunk = (ucx_memchunk*) pool->data[i]; - if(chunk) { - if(chunk->destructor) { - chunk->destructor(&(chunk->c)); - } - free(chunk); +void cxMempoolDestroy(CxMempool *pool) { + struct cx_mempool_memory_s *mem; + cx_for_n(i, pool->size) { + mem = pool->data[i]; + if (mem->destructor) { + mem->destructor(mem->c); } + free(mem); } free(pool->data); - free(pool->allocator); + free((void*) pool->allocator); free(pool); } -void ucx_mempool_set_destr(void *ptr, ucx_destructor func) { - *(ucx_destructor*)((char*)ptr-sizeof(ucx_destructor)) = func; +void cxMempoolSetDestructor( + void *ptr, + cx_destructor_func func +) { + *(cx_destructor_func *) ((char *) ptr - sizeof(cx_destructor_func)) = func; } -void ucx_mempool_reg_destr(UcxMempool *pool, void *ptr, ucx_destructor destr) { - ucx_regdestr *rd = (ucx_regdestr*)ucx_mempool_malloc( +struct cx_mempool_foreign_mem_s { + cx_destructor_func destr; + void* mem; +}; + +static void cx_mempool_destr_foreign_mem(void* ptr) { + struct cx_mempool_foreign_mem_s *fm = ptr; + fm->destr(fm->mem); +} + +int cxMempoolRegister( + CxMempool *pool, + void *memory, + cx_destructor_func destr +) { + struct cx_mempool_foreign_mem_s *fm = cx_mempool_malloc( pool, - sizeof(ucx_regdestr)); - rd->destructor = destr; - rd->ptr = ptr; - ucx_mempool_set_destr(rd, ucx_mempool_shared_destr); + sizeof(struct cx_mempool_foreign_mem_s) + ); + if (fm == NULL) return 1; + + fm->mem = memory; + fm->destr = destr; + *(cx_destructor_func *) ((char *) fm - sizeof(cx_destructor_func)) = cx_mempool_destr_foreign_mem; + + return 0; } +static cx_allocator_class cx_mempool_allocator_class = { + cx_mempool_malloc, + cx_mempool_realloc, + cx_mempool_calloc, + cx_mempool_free +}; + +CxMempool *cxMempoolCreate( + size_t capacity, + cx_destructor_func destr +) { + size_t poolsize; + if (cx_szmul(capacity, sizeof(struct cx_mempool_memory_s*), &poolsize)) { + return NULL; + } + + struct cx_mempool_s *pool = + malloc(sizeof(struct cx_mempool_s)); + if (pool == NULL) { + return NULL; + } + + CxAllocator *provided_allocator = malloc(sizeof(CxAllocator)); + if (provided_allocator == NULL) { + free(pool); + return NULL; + } + provided_allocator->cl = &cx_mempool_allocator_class; + provided_allocator->data = pool; + + pool->allocator = provided_allocator; + + pool->data = malloc(poolsize); + if (pool->data == NULL) { + free(provided_allocator); + free(pool); + return NULL; + } + + pool->size = 0; + pool->capacity = capacity; + pool->auto_destr = destr; + + return (CxMempool *) pool; +}