|
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 |