Thu, 23 Jan 2025 01:33:36 +0100
create new page structure
relates to #451
1141 | 1 | # mempool.h |
2 | ||
3 | A memory pool is providing an allocator implementation that automatically deallocates the memory upon its destruction. | |
4 | It also allows you to register destructor functions for the allocated memory, which are automatically called before | |
5 | the memory is deallocated. | |
6 | Additionally, you may also register _independent_ destructor functions within a pool in case some external library | |
7 | allocated memory for you, which should be freed together with this pool. | |
8 | ||
9 | Many UCX features support the use of an allocator. | |
10 | The [strings](#string), for instance, provide several functions suffixed with `_a` that allow specifying an allocator. | |
11 | You can use this to keep track of the memory occupied by dynamically allocated strings and cleanup everything with | |
12 | just a single call to `cxMempoolFree()`. | |
13 | ||
14 | The following code illustrates this on the example of reading a CSV file into memory. | |
15 | ```C | |
16 | #include <stdio.h> | |
17 | #include <cx/mempool.h> | |
18 | #include <cx/linked_list.h> | |
19 | #include <cx/string.h> | |
20 | #include <cx/buffer.h> | |
21 | #include <cx/utils.h> | |
22 | ||
23 | typedef struct { | |
24 | cxstring column_a; | |
25 | cxstring column_b; | |
26 | cxstring column_c; | |
27 | } CSVData; | |
28 | ||
29 | int main(void) { | |
30 | CxMempool* pool = cxBasicMempoolCreate(128); | |
31 | ||
32 | FILE *f = fopen("test.csv", "r"); | |
33 | if (!f) { | |
34 | perror("Cannot open file"); | |
35 | return 1; | |
36 | } | |
37 | // close the file automatically at pool destruction | |
38 | cxMempoolRegister(pool, f, (cx_destructor_func) fclose); | |
39 | ||
40 | // create a buffer using the memory pool for destruction | |
41 | CxBuffer *content = cxBufferCreate(NULL, 256, pool->allocator, CX_BUFFER_AUTO_EXTEND); | |
42 | ||
43 | // read the file into the buffer and turn it into a string | |
44 | cx_stream_copy(f, content, (cx_read_func) fread, cxBufferWriteFunc); | |
45 | fclose(f); | |
46 | cxstring contentstr = cx_strn(content->space, content->size); | |
47 | ||
48 | // split the string into lines - use the mempool for allocating the target array | |
49 | cxstring* lines; | |
50 | size_t lc = cx_strsplit_a(pool->allocator, contentstr, | |
51 | CX_STR("\n"), SIZE_MAX, &lines); | |
52 | ||
53 | // skip the header and parse the remaining data into a linked list | |
54 | // the nodes of the linked list shall also be allocated by the mempool | |
55 | CxList* datalist = cxLinkedListCreate(pool->allocator, NULL, sizeof(CSVData)); | |
56 | for (size_t i = 1 ; i < lc ; i++) { | |
57 | if (lines[i].length == 0) continue; | |
58 | cxstring fields[3]; | |
59 | size_t fc = cx_strsplit(lines[i], CX_STR(";"), 3, fields); | |
60 | if (fc != 3) { | |
61 | fprintf(stderr, "Syntax error in line %zu.\n", i); | |
62 | cxMempoolFree(pool); | |
63 | return 1; | |
64 | } | |
65 | CSVData data; | |
66 | data.column_a = fields[0]; | |
67 | data.column_b = fields[1]; | |
68 | data.column_c = fields[2]; | |
69 | cxListAdd(datalist, &data); | |
70 | } | |
71 | ||
72 | // iterate through the list and output the data | |
73 | CxIterator iter = cxListIterator(datalist); | |
74 | cx_foreach(CSVData*, data, iter) { | |
75 | printf("Column A: %.*s | " | |
76 | "Column B: %.*s | " | |
77 | "Column C: %.*s\n", | |
78 | (int)data->column_a.length, data->column_a.ptr, | |
79 | (int)data->column_b.length, data->column_b.ptr, | |
80 | (int)data->column_c.length, data->column_c.ptr | |
81 | ); | |
82 | } | |
83 | ||
84 | // cleanup everything, no manual free() needed | |
85 | cxMempoolFree(pool); | |
86 | ||
87 | return 0; | |
88 | } | |
89 | ``` | |
90 |