docs/Writerside/topics/mempool.h.md

branch
docs/3.1
changeset 1141
a06a2d27c043
child 1142
9437530176bc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/Writerside/topics/mempool.h.md	Thu Jan 23 01:33:36 2025 +0100
@@ -0,0 +1,90 @@
+# 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