# HG changeset patch # User Mike Becker # Date 1526295277 -7200 # Node ID 8628147734d6bc3fb3ab5051d38c5eab27bfec55 # Parent 0f83916c163934f21deb5c25ea0d4c145c327cf7 comprehensive code example for the memory pool diff -r 0f83916c1639 -r 8628147734d6 docs/src/modules.md --- a/docs/src/modules.md Sun May 13 17:34:06 2018 +0200 +++ b/docs/src/modules.md Mon May 14 12:54:37 2018 +0200 @@ -352,9 +352,110 @@ This pool allows you to register destructor functions for the allocated memory, which are automatically called on the destruction of the pool. But you may also register *independent* destructor functions within a pool in -case, some external library allocated memory for you, which you wish to be +case some external library allocated memory for you, which should be destroyed together with this pool. +Many UCX modules support the use of an allocator. +The [String Module](#string), for instance, provides the `sstrdup_a()` function, +which uses the specified allocator to allocate the memory for the duplicated +string. +This way, you can use a `UcxMempool` to keep track of the memory occupied by +duplicated strings and cleanup everything with just a single call to +`ucx_mempool_destroy()`. + +### Read CSV data into a structure + +The following code example shows some of the basic memory pool functions and +how they can be used with other UCX modules. +```C +#include +#include +#include +#include +#include +#include + +typedef struct { + sstr_t column_a; + sstr_t column_b; + sstr_t column_c; +} CSVData; + +int main(int argc, char** argv) { + + UcxMempool* pool = ucx_mempool_new(128); + + FILE *f = fopen("test.csv", "r"); + if (!f) { + perror("Cannot open file"); + return 1; + } + /* close the file automatically at pool destruction*/ + ucx_mempool_reg_destr(pool, f, (ucx_destructor) fclose); + + /* create a buffer and register it at the memory pool for destruction */ + UcxBuffer* content = ucx_buffer_new(NULL, 256, UCX_BUFFER_AUTOEXTEND); + ucx_mempool_reg_destr(pool, content, (ucx_destructor) ucx_buffer_free); + + /* read the file and split it by lines first */ + ucx_stream_copy(f, content, fread, ucx_buffer_write); + sstr_t contentstr = ucx_buffer_to_sstr(content); + ssize_t lc = 0; + sstr_t* lines = sstrsplit_a(pool->allocator, contentstr, S("\n"), &lc); + + /* skip the header and parse the remaining data */ + UcxList* datalist = NULL; + for (size_t i = 1 ; i < lc ; i++) { + if (lines[i].length == 0) continue; + ssize_t fc = 3; + sstr_t* fields = sstrsplit_a(pool->allocator, lines[i], S(";"), &fc); + if (fc != 3) { + fprintf(stderr, "Syntax error in line %zu.\n", i); + ucx_mempool_destroy(pool); + return 1; + } + CSVData* data = ucx_mempool_malloc(pool, sizeof(CSVData)); + data->column_a = fields[0]; + data->column_b = fields[1]; + data->column_c = fields[2]; + datalist = ucx_list_append_a(pool->allocator, datalist, data); + } + + /* control output */ + UCX_FOREACH(elem, datalist) { + CSVData* data = elem->data; + printf("Column A: %" PRIsstr " | " + "Column B: %" PRIsstr " | " + "Column C: %" PRIsstr "\n", + SFMT(data->column_a), SFMT(data->column_b), SFMT(data->column_c) + ); + } + + /* cleanup everything, no manual free() needed */ + ucx_mempool_destroy(pool); + + return 0; +} +``` + +### Overriding the default destructor + +Sometimes you need to allocate memory with `ucx_mempool_malloc()`, but the +memory is not supposed to be freed with a simple call to `free()`. +In this case, you can overwrite the default destructor as follows: +```C + MyObject* obj = ucx_mempool_malloc(pool, sizeof(MyObject)); + + /* some special initialization with own resource management */ + my_object_init(obj); + + /* register destructor function */ + ucx_mempool_set_destr(obj, (ucx_destructor) my_object_destroy); +``` +But aware, that your destructor function should not free any memory, that is +also managed by the pool. +Otherwise you might be risking a double-free. + ## Properties *Header file:* [properties.h](api/properties_8h.html)