src/basic_mempool.c

Sun, 21 May 2023 16:22:09 +0200

author
Mike Becker <universe@uap-core.de>
date
Sun, 21 May 2023 16:22:09 +0200
changeset 710
2dd409ed056f
parent 650
77021e06b1a8
permissions
-rw-r--r--

fix const-ness of non-mutating iterator creation for maps

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@571 29 #include "cx/basic_mempool.h"
universe@571 30 #include "cx/utils.h"
universe@571 31 #include <string.h>
universe@571 32
universe@571 33 #define of_chk_(n) if (SIZE_MAX - sizeof(cx_destructor_func) < (n)) return NULL
universe@571 34
universe@571 35 /** Internal structure for denoting pooled memory. */
universe@571 36 typedef struct {
universe@571 37 /** The destructor. */
universe@571 38 cx_destructor_func destructor;
universe@571 39 /**
universe@571 40 * Access to the first byte of the polled memory.
universe@571 41 */
universe@571 42 char c;
universe@571 43 } cx_basic_mempool_memory;
universe@571 44
universe@571 45 static int cx_basic_mempool_chcap(
universe@571 46 struct cx_basic_mempool_s *pool,
universe@571 47 size_t newcap
universe@571 48 ) {
universe@571 49 if (newcap < pool->ndata) {
universe@571 50 return 1;
universe@571 51 }
universe@571 52
universe@571 53 size_t newcapsz;
universe@571 54 if (cx_szmul(newcap, sizeof(void *), &newcapsz)) {
universe@571 55 return 1;
universe@571 56 }
universe@571 57
universe@571 58 void **data = realloc(pool->data, newcapsz);
universe@571 59 if (data) {
universe@571 60 pool->data = data;
universe@571 61 pool->size = newcap;
universe@571 62 return 0;
universe@571 63 } else {
universe@571 64 return 1;
universe@571 65 }
universe@571 66 }
universe@571 67
universe@571 68 void *cx_malloc_basic_mempool(
universe@571 69 void *data,
universe@571 70 size_t n
universe@571 71 ) {
universe@571 72 of_chk_(n);
universe@571 73 struct cx_basic_mempool_s *pool = data;
universe@571 74
universe@571 75 if (pool->ndata >= pool->size) {
universe@571 76 size_t newcap = pool->size * 2;
universe@571 77 if (newcap < pool->size || cx_basic_mempool_chcap(pool, newcap)) {
universe@571 78 return NULL;
universe@571 79 }
universe@571 80 }
universe@571 81
universe@572 82 cx_basic_mempool_memory *mem = malloc(sizeof(cx_destructor_func) + n);
universe@571 83 if (mem == NULL) {
universe@571 84 return NULL;
universe@571 85 }
universe@571 86
universe@571 87 mem->destructor = NULL;
universe@571 88 pool->data[pool->ndata] = mem;
universe@571 89 pool->ndata++;
universe@571 90
universe@571 91 return &(mem->c);
universe@571 92 }
universe@571 93
universe@571 94 void *cx_calloc_basic_mempool(
universe@571 95 void *data,
universe@571 96 size_t nelem,
universe@571 97 size_t elsize
universe@571 98 ) {
universe@571 99 size_t msz;
universe@571 100 if (cx_szmul(nelem, elsize, &msz)) {
universe@571 101 return NULL;
universe@571 102 }
universe@571 103 void *ptr = cx_malloc_basic_mempool(data, msz);
universe@571 104 if (ptr == NULL) {
universe@571 105 return NULL;
universe@571 106 }
universe@571 107 memset(ptr, 0, nelem * elsize);
universe@571 108 return ptr;
universe@571 109 }
universe@571 110
universe@571 111 void *cx_realloc_basic_mempool(
universe@571 112 void *data,
universe@571 113 void *ptr,
universe@571 114 size_t n
universe@571 115 ) {
universe@571 116 of_chk_(n);
universe@571 117 struct cx_basic_mempool_s *pool = data;
universe@571 118
universe@571 119 char *mem = ((char *) ptr) - sizeof(cx_destructor_func);
universe@572 120 char *newm = (char *) realloc(mem, n + sizeof(cx_destructor_func));
universe@571 121 if (newm == NULL) {
universe@571 122 return NULL;
universe@571 123 }
universe@571 124 if (mem != newm) {
universe@571 125 cx_for_n(i, pool->ndata) {
universe@571 126 if (pool->data[i] == mem) {
universe@571 127 pool->data[i] = newm;
universe@571 128 return newm + sizeof(cx_destructor_func);
universe@571 129 }
universe@571 130 }
universe@571 131 abort();
universe@571 132 } else {
universe@571 133 return newm + sizeof(cx_destructor_func);
universe@571 134 }
universe@571 135 }
universe@571 136
universe@571 137 void cx_free_basic_mempool(
universe@571 138 void *data,
universe@571 139 void *ptr
universe@571 140 ) {
universe@571 141 struct cx_basic_mempool_s *pool = data;
universe@571 142
universe@571 143 cx_basic_mempool_memory *mem = (cx_basic_mempool_memory *)
universe@571 144 ((char *) ptr - sizeof(cx_destructor_func));
universe@571 145 cx_for_n(i, pool->ndata) {
universe@571 146 if (mem == pool->data[i]) {
universe@571 147 if (mem->destructor != NULL) {
universe@571 148 mem->destructor(&(mem->c));
universe@571 149 }
universe@572 150 free(mem);
universe@571 151 size_t last_index = pool->ndata - 1;
universe@571 152 if (i != last_index) {
universe@571 153 pool->data[i] = pool->data[last_index];
universe@571 154 pool->data[last_index] = NULL;
universe@571 155 }
universe@571 156 pool->ndata--;
universe@571 157 return;
universe@571 158 }
universe@571 159 }
universe@571 160 abort();
universe@571 161 }
universe@571 162
universe@571 163 void cx_basic_mempool_destroy(CxMempool *p) {
universe@571 164 struct cx_basic_mempool_s *pool = (struct cx_basic_mempool_s *) p;
universe@571 165 cx_basic_mempool_memory *mem;
universe@571 166 cx_for_n(i, pool->ndata) {
universe@571 167 mem = (cx_basic_mempool_memory *) pool->data[i];
universe@571 168 if (mem) {
universe@571 169 if (mem->destructor) {
universe@571 170 mem->destructor(&(mem->c));
universe@571 171 }
universe@572 172 free(mem);
universe@571 173 }
universe@571 174 }
universe@571 175 free(pool->data);
universe@571 176 free((void *) p->allocator);
universe@571 177 free(pool);
universe@571 178 }
universe@571 179
universe@571 180 void cx_basic_mempool_set_destr(
universe@571 181 __attribute__((__unused__)) CxMempool *pool,
universe@571 182 void *ptr,
universe@571 183 cx_destructor_func func
universe@571 184 ) {
universe@571 185 *(cx_destructor_func *) ((char *) ptr - sizeof(cx_destructor_func)) = func;
universe@571 186 }
universe@571 187
universe@571 188 static cx_allocator_class cx_basic_mempool_allocator_class = {
universe@571 189 cx_malloc_basic_mempool,
universe@571 190 cx_realloc_basic_mempool,
universe@571 191 cx_calloc_basic_mempool,
universe@571 192 cx_free_basic_mempool
universe@571 193 };
universe@571 194
universe@571 195 static cx_mempool_class cx_basic_mempool_class = {
universe@571 196 cx_basic_mempool_destroy,
universe@571 197 cx_basic_mempool_set_destr,
universe@571 198 };
universe@571 199
universe@572 200 CxMempool *cxBasicMempoolCreate(size_t capacity) {
universe@571 201 size_t poolsize;
universe@571 202 if (cx_szmul(capacity, sizeof(void *), &poolsize)) {
universe@571 203 return NULL;
universe@571 204 }
universe@571 205
universe@571 206 struct cx_basic_mempool_s *pool =
universe@571 207 malloc(sizeof(struct cx_basic_mempool_s));
universe@571 208 if (pool == NULL) {
universe@571 209 return NULL;
universe@571 210 }
universe@571 211
universe@571 212
universe@571 213 CxAllocator *provided_allocator = malloc(sizeof(CxAllocator));
universe@571 214 if (!provided_allocator) {
universe@571 215 free(pool);
universe@571 216 return NULL;
universe@571 217 }
universe@571 218 provided_allocator->cl = &cx_basic_mempool_allocator_class;
universe@571 219 provided_allocator->data = pool;
universe@571 220
universe@571 221 pool->base.cl = &cx_basic_mempool_class;
universe@571 222 pool->base.allocator = provided_allocator;
universe@571 223
universe@571 224 pool->data = malloc(poolsize);
universe@571 225 if (pool->data == NULL) {
universe@571 226 free(provided_allocator);
universe@571 227 free(pool);
universe@571 228 return NULL;
universe@571 229 }
universe@571 230
universe@571 231 pool->ndata = 0;
universe@571 232 pool->size = capacity;
universe@571 233
universe@571 234 return (CxMempool *) pool;
universe@571 235 }

mercurial