--- /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; +} +``` +