docs/Writerside/topics/mempool.h.md

changeset 1188
b0300de92b72
parent 1174
ee473780cc0d
equal deleted inserted replaced
1187:0f70bb04f7ba 1188:b0300de92b72
1 # Memory Pool
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
7 Additionally, you may also register _independent_ destructor functions.
8 This can be useful, for example, when some library allocates memory that you wish to destroy when the memory pool gets destroyed.
9
10 A memory pool can be used with all UCX features that support the use of an [allocator](allocator.h.md).
11 For example, the UCX [string](string.h.md) functions provide several variants suffixed with `_a` for that purpose.
12
13 ## Overview
14
15 ```C
16 #include <cx/mempool.h>
17
18 CxMempool *cxMempoolCreate(size_t capacity, cx_destructor_func fnc);
19
20 CxMempool *cxMempoolCreateSimple(size_t capacity);
21
22 void cxMempoolFree(CxMempool *pool);
23
24 void cxMempoolSetDestructor(void *memory, cx_destructor_func fnc);
25
26 void cxMempoolRemoveDestructor(void *memory);
27
28 int cxMempoolRegister(CxMempool *pool, void *memory,
29 cx_destructor_func fnc);
30 ```
31
32 ## Description
33
34 A memory pool is created with the `cxMempoolCreate()` function with a default `capacity`
35 and an optional default destructor function `fnc`.
36 If specified, the default destructor function is registered for all freshly allocated memory within the pool,
37 as if `cxMempoolSetDestructor()` was called immediately after allocation.
38 When you set `fnc` is to `NULL` during pool creation, or use `cxMempoolCreateSimple`, no default destructor is registered.
39
40 After creating a memory pool `CxMempool *mpool`, you can access the provided allocator via `mpool->allocator`.
41
42 The functions `cxMempoolSetDestructor()` and `cxMempoolRemoveDestructor()` can be used to assign a specific destructor
43 function to an allocated object or remove any assigned destructor function, respectively.
44 The `memory` pointer points to the allocated object, which must have been allocated by any `CxMempool`'s provided allocator.
45
46 The `cxMempoolRegister()` function allocates a new wrapper object for `memory` with `pool`'s allocator that
47 will call the specified destructor function when destroyed.
48 Usually this function returns zero except for platforms where memory allocations are likely to fail,
49 in which case a non-zero value is returned.
50
51 ## Order of Destruction
52
53 When you call `cxMempoolFree()` the following actions are performed:
54
55 1. In any order, for each object in the pool
56 1. the destructor function assigned to that object is called
57 2. the object's memory is deallocated
58 2. The pool memory is deallocated
59 3. The pool structure is deallocated
60
61 ## Example
62
63 The following code illustrates how the contents of a CSV file are read into pooled memory.
64 ```C
65 #include <stdio.h>
66 #include <cx/mempool.h>
67 #include <cx/linked_list.h>
68 #include <cx/string.h>
69 #include <cx/buffer.h>
70 #include <cx/utils.h>
71
72 typedef struct {
73 cxstring column_a;
74 cxstring column_b;
75 cxstring column_c;
76 } CSVData;
77
78 int main(void) {
79 // create a simple pool for various different objects
80 CxMempool* pool = cxMempoolCreateSimple(128);
81
82 FILE *f = fopen("test.csv", "r");
83 if (f == NULL) {
84 perror("Cannot open file");
85 return 1;
86 }
87 // close the file automatically at pool destruction
88 cxMempoolRegister(pool, f, (cx_destructor_func) fclose);
89
90 // create a buffer using the memory pool for destruction
91 CxBuffer *content = cxBufferCreate(
92 NULL, 256, pool->allocator, CX_BUFFER_AUTO_EXTEND
93 );
94
95 // read the file into the buffer and turn it into a string
96 cx_stream_copy(
97 f, content, (cx_read_func) fread, cxBufferWriteFunc
98 );
99 fclose(f);
100 cxstring contentstr = cx_strn(content->space, content->size);
101
102 // split the string into lines
103 // use the memory pool to allocate the target array
104 cxstring* lines;
105 size_t lc = cx_strsplit_a(
106 pool->allocator, contentstr, cx_str("\n"), SIZE_MAX, &lines
107 );
108
109 // skip the header and parse the remaining data into a linked list
110 // the nodes of the list shall also be allocated by the pool
111 CxList* datalist = cxLinkedListCreate(
112 pool->allocator, NULL, sizeof(CSVData)
113 );
114 for (size_t i = 1 ; i < lc ; i++) {
115 if (lines[i].length == 0) continue;
116 cxstring fields[3];
117 size_t fc = cx_strsplit(lines[i], cx_str(";"), 3, fields);
118 if (fc != 3) {
119 fprintf(stderr, "Syntax error in line %zu.\n", i);
120 cxMempoolFree(pool);
121 return 1;
122 }
123 CSVData data;
124 data.column_a = fields[0];
125 data.column_b = fields[1];
126 data.column_c = fields[2];
127 cxListAdd(datalist, &data);
128 }
129
130 // iterate through the list and output the data
131 CxIterator iter = cxListIterator(datalist);
132 cx_foreach(CSVData*, data, iter) {
133 printf("Column A: %.*s | "
134 "Column B: %.*s | "
135 "Column C: %.*s\n",
136 (int)data->column_a.length, data->column_a.ptr,
137 (int)data->column_b.length, data->column_b.ptr,
138 (int)data->column_c.length, data->column_c.ptr
139 );
140 }
141
142 // cleanup everything, no manual free() needed
143 cxMempoolFree(pool);
144
145 return 0;
146 }
147 ```
148
149 <seealso>
150 <category ref="apidoc">
151 <a href="https://ucx.sourceforge.io/api/mempool_8h.html">mempool.h</a>
152 </category>
153 </seealso>

mercurial