src/mempool.c

Fri, 12 Apr 2024 21:48:12 +0200

author
Mike Becker <universe@uap-core.de>
date
Fri, 12 Apr 2024 21:48:12 +0200
changeset 849
edb9f875b7f9
parent 727
d92a59f5d261
permissions
-rw-r--r--

improves interface of cx_sprintf() variants

universe@571 1 /*
universe@571 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
universe@571 3 *
universe@571 4 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
universe@571 5 *
universe@571 6 * Redistribution and use in source and binary forms, with or without
universe@571 7 * modification, are permitted provided that the following conditions are met:
universe@571 8 *
universe@571 9 * 1. Redistributions of source code must retain the above copyright
universe@571 10 * notice, this list of conditions and the following disclaimer.
universe@571 11 *
universe@571 12 * 2. Redistributions in binary form must reproduce the above copyright
universe@571 13 * notice, this list of conditions and the following disclaimer in the
universe@571 14 * documentation and/or other materials provided with the distribution.
universe@571 15 *
universe@571 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
universe@571 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
universe@571 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
universe@571 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
universe@571 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
universe@571 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
universe@571 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
universe@571 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
universe@571 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
universe@571 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
universe@571 26 * POSSIBILITY OF SUCH DAMAGE.
universe@571 27 */
universe@571 28
universe@727 29 #include "cx/mempool.h"
universe@571 30 #include "cx/utils.h"
universe@571 31 #include <string.h>
universe@571 32
universe@727 33 struct cx_mempool_memory_s {
universe@571 34 /** The destructor. */
universe@571 35 cx_destructor_func destructor;
universe@727 36 /** The actual memory. */
universe@727 37 char c[];
universe@727 38 };
universe@571 39
universe@727 40 static void *cx_mempool_malloc(
universe@727 41 void *p,
universe@727 42 size_t n
universe@571 43 ) {
universe@727 44 struct cx_mempool_s *pool = p;
universe@727 45
universe@727 46 if (pool->size >= pool->capacity) {
universe@727 47 size_t newcap = pool->capacity - (pool->capacity % 16) + 16;
universe@727 48 struct cx_mempool_memory_s **newdata = realloc(pool->data, newcap*sizeof(struct cx_mempool_memory_s*));
universe@727 49 if (newdata == NULL) {
universe@727 50 return NULL;
universe@727 51 }
universe@727 52 pool->data = newdata;
universe@727 53 pool->capacity = newcap;
universe@571 54 }
universe@571 55
universe@727 56 struct cx_mempool_memory_s *mem = malloc(sizeof(cx_destructor_func) + n);
universe@571 57 if (mem == NULL) {
universe@571 58 return NULL;
universe@571 59 }
universe@571 60
universe@727 61 mem->destructor = pool->auto_destr;
universe@727 62 pool->data[pool->size] = mem;
universe@727 63 pool->size++;
universe@571 64
universe@727 65 return mem->c;
universe@571 66 }
universe@571 67
universe@727 68 static void *cx_mempool_calloc(
universe@727 69 void *p,
universe@571 70 size_t nelem,
universe@571 71 size_t elsize
universe@571 72 ) {
universe@571 73 size_t msz;
universe@571 74 if (cx_szmul(nelem, elsize, &msz)) {
universe@571 75 return NULL;
universe@571 76 }
universe@727 77 void *ptr = cx_mempool_malloc(p, msz);
universe@571 78 if (ptr == NULL) {
universe@571 79 return NULL;
universe@571 80 }
universe@571 81 memset(ptr, 0, nelem * elsize);
universe@571 82 return ptr;
universe@571 83 }
universe@571 84
universe@727 85 static void *cx_mempool_realloc(
universe@727 86 void *p,
universe@571 87 void *ptr,
universe@571 88 size_t n
universe@571 89 ) {
universe@727 90 struct cx_mempool_s *pool = p;
universe@571 91
universe@727 92 struct cx_mempool_memory_s *mem, *newm;
universe@727 93 mem = (struct cx_mempool_memory_s*)(((char *) ptr) - sizeof(cx_destructor_func));
universe@727 94 newm = realloc(mem, n + sizeof(cx_destructor_func));
universe@727 95
universe@571 96 if (newm == NULL) {
universe@571 97 return NULL;
universe@571 98 }
universe@571 99 if (mem != newm) {
universe@727 100 cx_for_n(i, pool->size) {
universe@571 101 if (pool->data[i] == mem) {
universe@571 102 pool->data[i] = newm;
universe@727 103 return ((char*)newm) + sizeof(cx_destructor_func);
universe@571 104 }
universe@571 105 }
universe@571 106 abort();
universe@571 107 } else {
universe@727 108 return ptr;
universe@571 109 }
universe@571 110 }
universe@571 111
universe@727 112 static void cx_mempool_free(
universe@727 113 void *p,
universe@571 114 void *ptr
universe@571 115 ) {
universe@727 116 struct cx_mempool_s *pool = p;
universe@571 117
universe@727 118 struct cx_mempool_memory_s *mem = (struct cx_mempool_memory_s *)
universe@571 119 ((char *) ptr - sizeof(cx_destructor_func));
universe@727 120
universe@727 121 cx_for_n(i, pool->size) {
universe@571 122 if (mem == pool->data[i]) {
universe@727 123 if (mem->destructor) {
universe@727 124 mem->destructor(mem->c);
universe@571 125 }
universe@572 126 free(mem);
universe@727 127 size_t last_index = pool->size - 1;
universe@571 128 if (i != last_index) {
universe@571 129 pool->data[i] = pool->data[last_index];
universe@571 130 pool->data[last_index] = NULL;
universe@571 131 }
universe@727 132 pool->size--;
universe@571 133 return;
universe@571 134 }
universe@571 135 }
universe@571 136 abort();
universe@571 137 }
universe@571 138
universe@727 139 void cxMempoolDestroy(CxMempool *pool) {
universe@727 140 struct cx_mempool_memory_s *mem;
universe@727 141 cx_for_n(i, pool->size) {
universe@727 142 mem = pool->data[i];
universe@727 143 if (mem->destructor) {
universe@727 144 mem->destructor(mem->c);
universe@571 145 }
universe@727 146 free(mem);
universe@571 147 }
universe@571 148 free(pool->data);
universe@727 149 free((void*) pool->allocator);
universe@571 150 free(pool);
universe@571 151 }
universe@571 152
universe@727 153 void cxMempoolSetDestructor(
universe@571 154 void *ptr,
universe@571 155 cx_destructor_func func
universe@571 156 ) {
universe@571 157 *(cx_destructor_func *) ((char *) ptr - sizeof(cx_destructor_func)) = func;
universe@571 158 }
universe@571 159
universe@727 160 struct cx_mempool_foreign_mem_s {
universe@727 161 cx_destructor_func destr;
universe@727 162 void* mem;
universe@571 163 };
universe@571 164
universe@727 165 static void cx_mempool_destr_foreign_mem(void* ptr) {
universe@727 166 struct cx_mempool_foreign_mem_s *fm = ptr;
universe@727 167 fm->destr(fm->mem);
universe@727 168 }
universe@727 169
universe@727 170 int cxMempoolRegister(
universe@727 171 CxMempool *pool,
universe@727 172 void *memory,
universe@727 173 cx_destructor_func destr
universe@727 174 ) {
universe@727 175 struct cx_mempool_foreign_mem_s *fm = cx_mempool_malloc(
universe@727 176 pool,
universe@727 177 sizeof(struct cx_mempool_foreign_mem_s)
universe@727 178 );
universe@727 179 if (fm == NULL) return 1;
universe@727 180
universe@727 181 fm->mem = memory;
universe@727 182 fm->destr = destr;
universe@727 183 *(cx_destructor_func *) ((char *) fm - sizeof(cx_destructor_func)) = cx_mempool_destr_foreign_mem;
universe@727 184
universe@727 185 return 0;
universe@727 186 }
universe@727 187
universe@727 188 static cx_allocator_class cx_mempool_allocator_class = {
universe@727 189 cx_mempool_malloc,
universe@727 190 cx_mempool_realloc,
universe@727 191 cx_mempool_calloc,
universe@727 192 cx_mempool_free
universe@571 193 };
universe@571 194
universe@727 195 CxMempool *cxMempoolCreate(
universe@727 196 size_t capacity,
universe@727 197 cx_destructor_func destr
universe@727 198 ) {
universe@571 199 size_t poolsize;
universe@727 200 if (cx_szmul(capacity, sizeof(struct cx_mempool_memory_s*), &poolsize)) {
universe@571 201 return NULL;
universe@571 202 }
universe@571 203
universe@727 204 struct cx_mempool_s *pool =
universe@727 205 malloc(sizeof(struct cx_mempool_s));
universe@571 206 if (pool == NULL) {
universe@571 207 return NULL;
universe@571 208 }
universe@571 209
universe@571 210 CxAllocator *provided_allocator = malloc(sizeof(CxAllocator));
universe@727 211 if (provided_allocator == NULL) {
universe@571 212 free(pool);
universe@571 213 return NULL;
universe@571 214 }
universe@727 215 provided_allocator->cl = &cx_mempool_allocator_class;
universe@571 216 provided_allocator->data = pool;
universe@571 217
universe@727 218 pool->allocator = provided_allocator;
universe@571 219
universe@571 220 pool->data = malloc(poolsize);
universe@571 221 if (pool->data == NULL) {
universe@571 222 free(provided_allocator);
universe@571 223 free(pool);
universe@571 224 return NULL;
universe@571 225 }
universe@571 226
universe@727 227 pool->size = 0;
universe@727 228 pool->capacity = capacity;
universe@727 229 pool->auto_destr = destr;
universe@571 230
universe@571 231 return (CxMempool *) pool;
universe@571 232 }

mercurial