src/basic_mempool.c

Sun, 13 Nov 2022 13:21:48 +0100

author
Mike Becker <universe@uap-core.de>
date
Sun, 13 Nov 2022 13:21:48 +0100
changeset 607
2d99e978dc34
parent 572
f0f99dd06d9f
child 650
77021e06b1a8
permissions
-rw-r--r--

implement array list ctor and dtor

also lays out the "glue level" functions

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

mercurial