# HG changeset patch # User Mike Becker # Date 1688213152 -7200 # Node ID 600d72644919eaf6e96618b7d57a8fd8a57c9415 # Parent 71c4ac35c1ce5ccc47d7569cf0b5afffab644c97 add mempool example diff -r 71c4ac35c1ce -r 600d72644919 docs/src/features.md --- 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 +#include +#include +#include +#include +#include + +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)