--- a/ucx/basic_mempool.c Sun Oct 01 09:23:47 2023 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,235 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * 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: - * - * 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 HOLDER 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 "cx/basic_mempool.h" -#include "cx/utils.h" -#include <string.h> - -#define of_chk_(n) if (SIZE_MAX - sizeof(cx_destructor_func) < (n)) return NULL - -/** Internal structure for denoting pooled memory. */ -typedef struct { - /** The destructor. */ - cx_destructor_func destructor; - /** - * Access to the first byte of the polled memory. - */ - char c; -} cx_basic_mempool_memory; - -static int cx_basic_mempool_chcap( - struct cx_basic_mempool_s *pool, - size_t newcap -) { - if (newcap < pool->ndata) { - return 1; - } - - size_t newcapsz; - if (cx_szmul(newcap, sizeof(void *), &newcapsz)) { - return 1; - } - - void **data = realloc(pool->data, newcapsz); - if (data) { - pool->data = data; - pool->size = newcap; - return 0; - } else { - return 1; - } -} - -void *cx_malloc_basic_mempool( - void *data, - size_t n -) { - of_chk_(n); - struct cx_basic_mempool_s *pool = data; - - if (pool->ndata >= pool->size) { - size_t newcap = pool->size * 2; - if (newcap < pool->size || cx_basic_mempool_chcap(pool, newcap)) { - return NULL; - } - } - - cx_basic_mempool_memory *mem = malloc(sizeof(cx_destructor_func) + n); - if (mem == NULL) { - return NULL; - } - - mem->destructor = NULL; - pool->data[pool->ndata] = mem; - pool->ndata++; - - return &(mem->c); -} - -void *cx_calloc_basic_mempool( - void *data, - size_t nelem, - size_t elsize -) { - size_t msz; - if (cx_szmul(nelem, elsize, &msz)) { - return NULL; - } - void *ptr = cx_malloc_basic_mempool(data, msz); - if (ptr == NULL) { - return NULL; - } - memset(ptr, 0, nelem * elsize); - return ptr; -} - -void *cx_realloc_basic_mempool( - void *data, - void *ptr, - size_t n -) { - of_chk_(n); - struct cx_basic_mempool_s *pool = data; - - char *mem = ((char *) ptr) - sizeof(cx_destructor_func); - char *newm = (char *) realloc(mem, n + sizeof(cx_destructor_func)); - if (newm == NULL) { - return NULL; - } - if (mem != newm) { - cx_for_n(i, pool->ndata) { - if (pool->data[i] == mem) { - pool->data[i] = newm; - return newm + sizeof(cx_destructor_func); - } - } - abort(); - } else { - return newm + sizeof(cx_destructor_func); - } -} - -void cx_free_basic_mempool( - void *data, - void *ptr -) { - struct cx_basic_mempool_s *pool = data; - - cx_basic_mempool_memory *mem = (cx_basic_mempool_memory *) - ((char *) ptr - sizeof(cx_destructor_func)); - cx_for_n(i, pool->ndata) { - if (mem == pool->data[i]) { - if (mem->destructor != NULL) { - mem->destructor(&(mem->c)); - } - free(mem); - size_t last_index = pool->ndata - 1; - if (i != last_index) { - pool->data[i] = pool->data[last_index]; - pool->data[last_index] = NULL; - } - pool->ndata--; - return; - } - } - abort(); -} - -void cx_basic_mempool_destroy(CxMempool *p) { - struct cx_basic_mempool_s *pool = (struct cx_basic_mempool_s *) p; - cx_basic_mempool_memory *mem; - cx_for_n(i, pool->ndata) { - mem = (cx_basic_mempool_memory *) pool->data[i]; - if (mem) { - if (mem->destructor) { - mem->destructor(&(mem->c)); - } - free(mem); - } - } - free(pool->data); - free((void *) p->allocator); - free(pool); -} - -void cx_basic_mempool_set_destr( - __attribute__((__unused__)) CxMempool *pool, - void *ptr, - cx_destructor_func func -) { - *(cx_destructor_func *) ((char *) ptr - sizeof(cx_destructor_func)) = func; -} - -static cx_allocator_class cx_basic_mempool_allocator_class = { - cx_malloc_basic_mempool, - cx_realloc_basic_mempool, - cx_calloc_basic_mempool, - cx_free_basic_mempool -}; - -static cx_mempool_class cx_basic_mempool_class = { - cx_basic_mempool_destroy, - cx_basic_mempool_set_destr, -}; - -CxMempool *cxBasicMempoolCreate(size_t capacity) { - size_t poolsize; - if (cx_szmul(capacity, sizeof(void *), &poolsize)) { - return NULL; - } - - struct cx_basic_mempool_s *pool = - malloc(sizeof(struct cx_basic_mempool_s)); - if (pool == NULL) { - return NULL; - } - - - CxAllocator *provided_allocator = malloc(sizeof(CxAllocator)); - if (!provided_allocator) { - free(pool); - return NULL; - } - provided_allocator->cl = &cx_basic_mempool_allocator_class; - provided_allocator->data = pool; - - pool->base.cl = &cx_basic_mempool_class; - pool->base.allocator = provided_allocator; - - pool->data = malloc(poolsize); - if (pool->data == NULL) { - free(provided_allocator); - free(pool); - return NULL; - } - - pool->ndata = 0; - pool->size = capacity; - - return (CxMempool *) pool; -}