docs/Writerside/topics/mempool.h.md

Thu, 23 Jan 2025 01:33:36 +0100

author
Mike Becker <universe@uap-core.de>
date
Thu, 23 Jan 2025 01:33:36 +0100
branch
docs/3.1
changeset 1141
a06a2d27c043
child 1142
9437530176bc
permissions
-rw-r--r--

create new page structure

relates to #451

# mempool.h

A memory pool is providing an allocator implementation that automatically deallocates the memory upon its destruction.
It also allows you to register destructor functions for the allocated memory, which are automatically called before
the memory is deallocated.
Additionally, you may also register _independent_ destructor functions within a pool in case some external library
allocated memory for you, which should be freed together with this pool.

Many UCX features support the use of an allocator.
The [strings](#string), for instance, provide several functions suffixed with `_a` that allow specifying an allocator.
You can use this to keep track of the memory occupied by dynamically allocated strings and cleanup everything with
just a single call to `cxMempoolFree()`.

The following code illustrates this on the example of reading a CSV file into memory.
```C
#include <stdio.h>
#include <cx/mempool.h>
#include <cx/linked_list.h>
#include <cx/string.h>
#include <cx/buffer.h>
#include <cx/utils.h>

typedef struct {
    cxstring column_a;
    cxstring column_b;
    cxstring column_c;
} CSVData;

int main(void) {
    CxMempool* pool = cxBasicMempoolCreate(128);

    FILE *f = fopen("test.csv", "r");
    if (!f) {
        perror("Cannot open file");
        return 1;
    }
    // close the file automatically at pool destruction
    cxMempoolRegister(pool, f, (cx_destructor_func) fclose);

    // create a buffer using the memory pool for destruction
    CxBuffer *content = cxBufferCreate(NULL, 256, pool->allocator, CX_BUFFER_AUTO_EXTEND);

    // read the file into the buffer and turn it into a string
    cx_stream_copy(f, content, (cx_read_func) fread, cxBufferWriteFunc);
    fclose(f);
    cxstring contentstr = cx_strn(content->space, content->size);

    // split the string into lines - use the mempool for allocating the target array
    cxstring* lines;
    size_t lc = cx_strsplit_a(pool->allocator, contentstr,
                              CX_STR("\n"), SIZE_MAX, &lines);

    // skip the header and parse the remaining data into a linked list
    // the nodes of the linked list shall also be allocated by the mempool
    CxList* datalist = cxLinkedListCreate(pool->allocator, NULL, sizeof(CSVData));
    for (size_t i = 1 ; i < lc ; i++) {
        if (lines[i].length == 0) continue;
        cxstring fields[3];
        size_t fc = cx_strsplit(lines[i], CX_STR(";"), 3, fields);
        if (fc != 3) {
            fprintf(stderr, "Syntax error in line %zu.\n", i);
            cxMempoolFree(pool);
            return 1;
        }
        CSVData data;
        data.column_a = fields[0];
        data.column_b = fields[1];
        data.column_c = fields[2];
        cxListAdd(datalist, &data);
    }

    // iterate through the list and output the data
    CxIterator iter = cxListIterator(datalist);
    cx_foreach(CSVData*, data, iter) {
        printf("Column A: %.*s | "
               "Column B: %.*s | "
               "Column C: %.*s\n",
               (int)data->column_a.length, data->column_a.ptr,
               (int)data->column_b.length, data->column_b.ptr,
               (int)data->column_c.length, data->column_c.ptr
        );
    }

    // cleanup everything, no manual free() needed 
    cxMempoolFree(pool);

    return 0;
} 
```

mercurial