comprehensive code example for the memory pool

Mon, 14 May 2018 12:54:37 +0200

author
Mike Becker <universe@uap-core.de>
date
Mon, 14 May 2018 12:54:37 +0200
changeset 302
8628147734d6
parent 301
0f83916c1639
child 303
362679052788

comprehensive code example for the memory pool

docs/src/modules.md file | annotate | diff | comparison | revisions
--- 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 <stdio.h>
+#include <ucx/mempool.h>
+#include <ucx/list.h>
+#include <ucx/string.h>
+#include <ucx/buffer.h>
+#include <ucx/utils.h>
+
+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)  

mercurial