add mempool example

Sat, 01 Jul 2023 14:05:52 +0200

author
Mike Becker <universe@uap-core.de>
date
Sat, 01 Jul 2023 14:05:52 +0200
changeset 729
600d72644919
parent 728
71c4ac35c1ce
child 730
9fecb2769d32

add mempool example

docs/src/features.md file | annotate | diff | comparison | revisions
--- a/docs/src/features.md	Wed Jun 28 20:36:25 2023 +0200
+++ b/docs/src/features.md	Sat Jul 01 14:05:52 2023 +0200
@@ -91,6 +91,93 @@
 
 *Header file:* [mempool.h](api/mempool_8h.html)
 
+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 destroyed 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 `cxMempoolDestroy()`.
+
+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, (cx_write_func) cxBufferWrite);
+    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);
+            cxMempoolDestroy(pool);
+            return 1;
+        }
+        CSVData* data = cxMalloc(pool->allocator, sizeof(CSVData));
+        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 
+    cxMempoolDestroy(pool);
+
+    return 0;
+} 
+```
+
 ## Iterator
 
 *Header file:* [iterator.h](api/iterator_8h.html)

mercurial