1.1 --- a/src/basic_mempool.c Wed Jun 28 19:18:01 2023 +0200 1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 1.3 @@ -1,235 +0,0 @@ 1.4 -/* 1.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 1.6 - * 1.7 - * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 1.8 - * 1.9 - * Redistribution and use in source and binary forms, with or without 1.10 - * modification, are permitted provided that the following conditions are met: 1.11 - * 1.12 - * 1. Redistributions of source code must retain the above copyright 1.13 - * notice, this list of conditions and the following disclaimer. 1.14 - * 1.15 - * 2. Redistributions in binary form must reproduce the above copyright 1.16 - * notice, this list of conditions and the following disclaimer in the 1.17 - * documentation and/or other materials provided with the distribution. 1.18 - * 1.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 1.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 1.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 1.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 1.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 1.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 1.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 1.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 1.29 - * POSSIBILITY OF SUCH DAMAGE. 1.30 - */ 1.31 - 1.32 -#include "cx/basic_mempool.h" 1.33 -#include "cx/utils.h" 1.34 -#include <string.h> 1.35 - 1.36 -#define of_chk_(n) if (SIZE_MAX - sizeof(cx_destructor_func) < (n)) return NULL 1.37 - 1.38 -/** Internal structure for denoting pooled memory. */ 1.39 -typedef struct { 1.40 - /** The destructor. */ 1.41 - cx_destructor_func destructor; 1.42 - /** 1.43 - * Access to the first byte of the polled memory. 1.44 - */ 1.45 - char c; 1.46 -} cx_basic_mempool_memory; 1.47 - 1.48 -static int cx_basic_mempool_chcap( 1.49 - struct cx_basic_mempool_s *pool, 1.50 - size_t newcap 1.51 -) { 1.52 - if (newcap < pool->ndata) { 1.53 - return 1; 1.54 - } 1.55 - 1.56 - size_t newcapsz; 1.57 - if (cx_szmul(newcap, sizeof(void *), &newcapsz)) { 1.58 - return 1; 1.59 - } 1.60 - 1.61 - void **data = realloc(pool->data, newcapsz); 1.62 - if (data) { 1.63 - pool->data = data; 1.64 - pool->size = newcap; 1.65 - return 0; 1.66 - } else { 1.67 - return 1; 1.68 - } 1.69 -} 1.70 - 1.71 -void *cx_malloc_basic_mempool( 1.72 - void *data, 1.73 - size_t n 1.74 -) { 1.75 - of_chk_(n); 1.76 - struct cx_basic_mempool_s *pool = data; 1.77 - 1.78 - if (pool->ndata >= pool->size) { 1.79 - size_t newcap = pool->size * 2; 1.80 - if (newcap < pool->size || cx_basic_mempool_chcap(pool, newcap)) { 1.81 - return NULL; 1.82 - } 1.83 - } 1.84 - 1.85 - cx_basic_mempool_memory *mem = malloc(sizeof(cx_destructor_func) + n); 1.86 - if (mem == NULL) { 1.87 - return NULL; 1.88 - } 1.89 - 1.90 - mem->destructor = NULL; 1.91 - pool->data[pool->ndata] = mem; 1.92 - pool->ndata++; 1.93 - 1.94 - return &(mem->c); 1.95 -} 1.96 - 1.97 -void *cx_calloc_basic_mempool( 1.98 - void *data, 1.99 - size_t nelem, 1.100 - size_t elsize 1.101 -) { 1.102 - size_t msz; 1.103 - if (cx_szmul(nelem, elsize, &msz)) { 1.104 - return NULL; 1.105 - } 1.106 - void *ptr = cx_malloc_basic_mempool(data, msz); 1.107 - if (ptr == NULL) { 1.108 - return NULL; 1.109 - } 1.110 - memset(ptr, 0, nelem * elsize); 1.111 - return ptr; 1.112 -} 1.113 - 1.114 -void *cx_realloc_basic_mempool( 1.115 - void *data, 1.116 - void *ptr, 1.117 - size_t n 1.118 -) { 1.119 - of_chk_(n); 1.120 - struct cx_basic_mempool_s *pool = data; 1.121 - 1.122 - char *mem = ((char *) ptr) - sizeof(cx_destructor_func); 1.123 - char *newm = (char *) realloc(mem, n + sizeof(cx_destructor_func)); 1.124 - if (newm == NULL) { 1.125 - return NULL; 1.126 - } 1.127 - if (mem != newm) { 1.128 - cx_for_n(i, pool->ndata) { 1.129 - if (pool->data[i] == mem) { 1.130 - pool->data[i] = newm; 1.131 - return newm + sizeof(cx_destructor_func); 1.132 - } 1.133 - } 1.134 - abort(); 1.135 - } else { 1.136 - return newm + sizeof(cx_destructor_func); 1.137 - } 1.138 -} 1.139 - 1.140 -void cx_free_basic_mempool( 1.141 - void *data, 1.142 - void *ptr 1.143 -) { 1.144 - struct cx_basic_mempool_s *pool = data; 1.145 - 1.146 - cx_basic_mempool_memory *mem = (cx_basic_mempool_memory *) 1.147 - ((char *) ptr - sizeof(cx_destructor_func)); 1.148 - cx_for_n(i, pool->ndata) { 1.149 - if (mem == pool->data[i]) { 1.150 - if (mem->destructor != NULL) { 1.151 - mem->destructor(&(mem->c)); 1.152 - } 1.153 - free(mem); 1.154 - size_t last_index = pool->ndata - 1; 1.155 - if (i != last_index) { 1.156 - pool->data[i] = pool->data[last_index]; 1.157 - pool->data[last_index] = NULL; 1.158 - } 1.159 - pool->ndata--; 1.160 - return; 1.161 - } 1.162 - } 1.163 - abort(); 1.164 -} 1.165 - 1.166 -void cx_basic_mempool_destroy(CxMempool *p) { 1.167 - struct cx_basic_mempool_s *pool = (struct cx_basic_mempool_s *) p; 1.168 - cx_basic_mempool_memory *mem; 1.169 - cx_for_n(i, pool->ndata) { 1.170 - mem = (cx_basic_mempool_memory *) pool->data[i]; 1.171 - if (mem) { 1.172 - if (mem->destructor) { 1.173 - mem->destructor(&(mem->c)); 1.174 - } 1.175 - free(mem); 1.176 - } 1.177 - } 1.178 - free(pool->data); 1.179 - free((void *) p->allocator); 1.180 - free(pool); 1.181 -} 1.182 - 1.183 -void cx_basic_mempool_set_destr( 1.184 - __attribute__((__unused__)) CxMempool *pool, 1.185 - void *ptr, 1.186 - cx_destructor_func func 1.187 -) { 1.188 - *(cx_destructor_func *) ((char *) ptr - sizeof(cx_destructor_func)) = func; 1.189 -} 1.190 - 1.191 -static cx_allocator_class cx_basic_mempool_allocator_class = { 1.192 - cx_malloc_basic_mempool, 1.193 - cx_realloc_basic_mempool, 1.194 - cx_calloc_basic_mempool, 1.195 - cx_free_basic_mempool 1.196 -}; 1.197 - 1.198 -static cx_mempool_class cx_basic_mempool_class = { 1.199 - cx_basic_mempool_destroy, 1.200 - cx_basic_mempool_set_destr, 1.201 -}; 1.202 - 1.203 -CxMempool *cxBasicMempoolCreate(size_t capacity) { 1.204 - size_t poolsize; 1.205 - if (cx_szmul(capacity, sizeof(void *), &poolsize)) { 1.206 - return NULL; 1.207 - } 1.208 - 1.209 - struct cx_basic_mempool_s *pool = 1.210 - malloc(sizeof(struct cx_basic_mempool_s)); 1.211 - if (pool == NULL) { 1.212 - return NULL; 1.213 - } 1.214 - 1.215 - 1.216 - CxAllocator *provided_allocator = malloc(sizeof(CxAllocator)); 1.217 - if (!provided_allocator) { 1.218 - free(pool); 1.219 - return NULL; 1.220 - } 1.221 - provided_allocator->cl = &cx_basic_mempool_allocator_class; 1.222 - provided_allocator->data = pool; 1.223 - 1.224 - pool->base.cl = &cx_basic_mempool_class; 1.225 - pool->base.allocator = provided_allocator; 1.226 - 1.227 - pool->data = malloc(poolsize); 1.228 - if (pool->data == NULL) { 1.229 - free(provided_allocator); 1.230 - free(pool); 1.231 - return NULL; 1.232 - } 1.233 - 1.234 - pool->ndata = 0; 1.235 - pool->size = capacity; 1.236 - 1.237 - return (CxMempool *) pool; 1.238 -}