Sat, 19 Apr 2025 11:35:56 +0200
fix unnecessary explicit zero-terminator
|
1143
0559812df10c
assign proper names to the documentation topics
Mike Becker <universe@uap-core.de>
parents:
1142
diff
changeset
|
1 | # Memory Pool |
| 1141 | 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. | |
|
1168
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
6 | |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
7 | Additionally, you may also register _independent_ destructor functions. |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
8 | This can be useful, for example, when some library allocates memory that you wish to destroy when the memory pool gets destroyed. |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
9 | |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
10 | A memory pool can be used with all UCX features that support the use of an [allocator](allocator.h.md). |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
11 | For example, the UCX [string](string.h.md) functions provide several variants suffixed with `_a` for that purpose. |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
12 | |
|
1281
45746a08c59e
add cxMempoolTransfer() - partially resolves #640
Mike Becker <universe@uap-core.de>
parents:
1174
diff
changeset
|
13 | ## Basic Memory Management |
|
1168
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
14 | |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
15 | ```C |
|
1174
ee473780cc0d
add missing documentation about what header to include
Mike Becker <universe@uap-core.de>
parents:
1168
diff
changeset
|
16 | #include <cx/mempool.h> |
|
ee473780cc0d
add missing documentation about what header to include
Mike Becker <universe@uap-core.de>
parents:
1168
diff
changeset
|
17 | |
|
1168
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
18 | CxMempool *cxMempoolCreate(size_t capacity, cx_destructor_func fnc); |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
19 | |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
20 | CxMempool *cxMempoolCreateSimple(size_t capacity); |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
21 | |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
22 | void cxMempoolFree(CxMempool *pool); |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
23 | |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
24 | void cxMempoolSetDestructor(void *memory, cx_destructor_func fnc); |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
25 | |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
26 | void cxMempoolRemoveDestructor(void *memory); |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
27 | |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
28 | int cxMempoolRegister(CxMempool *pool, void *memory, |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
29 | cx_destructor_func fnc); |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
30 | ``` |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
31 | |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
32 | A memory pool is created with the `cxMempoolCreate()` function with a default `capacity` |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
33 | and an optional default destructor function `fnc`. |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
34 | If specified, the default destructor function is registered for all freshly allocated memory within the pool, |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
35 | as if `cxMempoolSetDestructor()` was called immediately after allocation. |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
36 | When you set `fnc` is to `NULL` during pool creation, or use `cxMempoolCreateSimple`, no default destructor is registered. |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
37 | |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
38 | After creating a memory pool `CxMempool *mpool`, you can access the provided allocator via `mpool->allocator`. |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
39 | |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
40 | The functions `cxMempoolSetDestructor()` and `cxMempoolRemoveDestructor()` can be used to assign a specific destructor |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
41 | function to an allocated object or remove any assigned destructor function, respectively. |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
42 | The `memory` pointer points to the allocated object, which must have been allocated by any `CxMempool`'s provided allocator. |
| 1141 | 43 | |
|
1168
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
44 | The `cxMempoolRegister()` function allocates a new wrapper object for `memory` with `pool`'s allocator that |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
45 | will call the specified destructor function when destroyed. |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
46 | Usually this function returns zero except for platforms where memory allocations are likely to fail, |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
47 | in which case a non-zero value is returned. |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
48 | |
|
1281
45746a08c59e
add cxMempoolTransfer() - partially resolves #640
Mike Becker <universe@uap-core.de>
parents:
1174
diff
changeset
|
49 | ### Order of Destruction |
|
1168
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
50 | |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
51 | When you call `cxMempoolFree()` the following actions are performed: |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
52 | |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
53 | 1. In any order, for each object in the pool |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
54 | 1. the destructor function assigned to that object is called |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
55 | 2. the object's memory is deallocated |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
56 | 2. The pool memory is deallocated |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
57 | 3. The pool structure is deallocated |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
58 | |
|
1281
45746a08c59e
add cxMempoolTransfer() - partially resolves #640
Mike Becker <universe@uap-core.de>
parents:
1174
diff
changeset
|
59 | ## Transfer Memory |
|
45746a08c59e
add cxMempoolTransfer() - partially resolves #640
Mike Becker <universe@uap-core.de>
parents:
1174
diff
changeset
|
60 | |
|
45746a08c59e
add cxMempoolTransfer() - partially resolves #640
Mike Becker <universe@uap-core.de>
parents:
1174
diff
changeset
|
61 | ```C |
|
45746a08c59e
add cxMempoolTransfer() - partially resolves #640
Mike Becker <universe@uap-core.de>
parents:
1174
diff
changeset
|
62 | #include <cx/mempool.h> |
|
45746a08c59e
add cxMempoolTransfer() - partially resolves #640
Mike Becker <universe@uap-core.de>
parents:
1174
diff
changeset
|
63 | |
|
45746a08c59e
add cxMempoolTransfer() - partially resolves #640
Mike Becker <universe@uap-core.de>
parents:
1174
diff
changeset
|
64 | int cxMempoolTransfer(CxMempool *source, CxMempool *dest); |
|
1283
89935fea4b7c
add cxMempoolTransferObject() - resolves #640
Mike Becker <universe@uap-core.de>
parents:
1282
diff
changeset
|
65 | |
|
89935fea4b7c
add cxMempoolTransferObject() - resolves #640
Mike Becker <universe@uap-core.de>
parents:
1282
diff
changeset
|
66 | int cxMempoolTransferObject(CxMempool *source, CxMempool *dest, |
|
89935fea4b7c
add cxMempoolTransferObject() - resolves #640
Mike Becker <universe@uap-core.de>
parents:
1282
diff
changeset
|
67 | const void *obj); |
|
1281
45746a08c59e
add cxMempoolTransfer() - partially resolves #640
Mike Becker <universe@uap-core.de>
parents:
1174
diff
changeset
|
68 | ``` |
|
45746a08c59e
add cxMempoolTransfer() - partially resolves #640
Mike Becker <universe@uap-core.de>
parents:
1174
diff
changeset
|
69 | |
|
45746a08c59e
add cxMempoolTransfer() - partially resolves #640
Mike Becker <universe@uap-core.de>
parents:
1174
diff
changeset
|
70 | Memory managed by a pool can be transferred to another pool. |
|
45746a08c59e
add cxMempoolTransfer() - partially resolves #640
Mike Becker <universe@uap-core.de>
parents:
1174
diff
changeset
|
71 | |
|
45746a08c59e
add cxMempoolTransfer() - partially resolves #640
Mike Becker <universe@uap-core.de>
parents:
1174
diff
changeset
|
72 | The function `cxMempoolTransfer()` transfers all memory managed and/or registered with the `source` pool to the `dest` pool. |
|
45746a08c59e
add cxMempoolTransfer() - partially resolves #640
Mike Becker <universe@uap-core.de>
parents:
1174
diff
changeset
|
73 | It also registers its allocator with the `dest` pool and creates a new allocator for the `source` pool. |
|
45746a08c59e
add cxMempoolTransfer() - partially resolves #640
Mike Becker <universe@uap-core.de>
parents:
1174
diff
changeset
|
74 | That means, that all references to the allocator of the `source` pool remain valid and continue to work with the `dest` pool. |
|
45746a08c59e
add cxMempoolTransfer() - partially resolves #640
Mike Becker <universe@uap-core.de>
parents:
1174
diff
changeset
|
75 | The transferred allocator will be destroyed when the `dest` pool gets destroyed. |
|
45746a08c59e
add cxMempoolTransfer() - partially resolves #640
Mike Becker <universe@uap-core.de>
parents:
1174
diff
changeset
|
76 | |
|
1283
89935fea4b7c
add cxMempoolTransferObject() - resolves #640
Mike Becker <universe@uap-core.de>
parents:
1282
diff
changeset
|
77 | The function `cxMempoolTransferObject()` transfers a _single_ object managed by the `source` pool to the `dest` pool. |
|
89935fea4b7c
add cxMempoolTransferObject() - resolves #640
Mike Becker <universe@uap-core.de>
parents:
1282
diff
changeset
|
78 | Memory that was registered with `cxMempoolRegister()` cannot be transferred this way. |
|
89935fea4b7c
add cxMempoolTransferObject() - resolves #640
Mike Becker <universe@uap-core.de>
parents:
1282
diff
changeset
|
79 | Also, if `obj` has a reference to `source->allocator`, it must be updated to `dest->allocator` manually. |
|
89935fea4b7c
add cxMempoolTransferObject() - resolves #640
Mike Becker <universe@uap-core.de>
parents:
1282
diff
changeset
|
80 | |
|
89935fea4b7c
add cxMempoolTransferObject() - resolves #640
Mike Becker <universe@uap-core.de>
parents:
1282
diff
changeset
|
81 | The functions returns zero when the transfer was successful and non-zero if a necessary memory allocation was not possible, |
|
1281
45746a08c59e
add cxMempoolTransfer() - partially resolves #640
Mike Becker <universe@uap-core.de>
parents:
1174
diff
changeset
|
82 | or the `source` and `dest` pointers point to the same pool. |
|
45746a08c59e
add cxMempoolTransfer() - partially resolves #640
Mike Becker <universe@uap-core.de>
parents:
1174
diff
changeset
|
83 | In case of an error, no memory is transferred and both pools are in a valid state. |
|
45746a08c59e
add cxMempoolTransfer() - partially resolves #640
Mike Becker <universe@uap-core.de>
parents:
1174
diff
changeset
|
84 | |
|
45746a08c59e
add cxMempoolTransfer() - partially resolves #640
Mike Becker <universe@uap-core.de>
parents:
1174
diff
changeset
|
85 | |
|
1168
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
86 | ## Example |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
87 | |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
88 | The following code illustrates how the contents of a CSV file are read into pooled memory. |
| 1141 | 89 | ```C |
| 90 | #include <stdio.h> | |
| 91 | #include <cx/mempool.h> | |
| 92 | #include <cx/linked_list.h> | |
| 93 | #include <cx/string.h> | |
| 94 | #include <cx/buffer.h> | |
| 95 | #include <cx/utils.h> | |
| 96 | ||
| 97 | typedef struct { | |
| 98 | cxstring column_a; | |
| 99 | cxstring column_b; | |
| 100 | cxstring column_c; | |
| 101 | } CSVData; | |
| 102 | ||
| 103 | int main(void) { | |
|
1168
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
104 | // create a simple pool for various different objects |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
105 | CxMempool* pool = cxMempoolCreateSimple(128); |
| 1141 | 106 | |
| 107 | FILE *f = fopen("test.csv", "r"); | |
|
1168
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
108 | if (f == NULL) { |
| 1141 | 109 | perror("Cannot open file"); |
| 110 | return 1; | |
| 111 | } | |
| 112 | // close the file automatically at pool destruction | |
| 113 | cxMempoolRegister(pool, f, (cx_destructor_func) fclose); | |
| 114 | ||
| 115 | // create a buffer using the memory pool for destruction | |
|
1168
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
116 | CxBuffer *content = cxBufferCreate( |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
117 | NULL, 256, pool->allocator, CX_BUFFER_AUTO_EXTEND |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
118 | ); |
| 1141 | 119 | |
| 120 | // read the file into the buffer and turn it into a string | |
|
1168
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
121 | cx_stream_copy( |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
122 | f, content, (cx_read_func) fread, cxBufferWriteFunc |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
123 | ); |
| 1141 | 124 | fclose(f); |
| 125 | cxstring contentstr = cx_strn(content->space, content->size); | |
| 126 | ||
|
1168
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
127 | // split the string into lines |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
128 | // use the memory pool to allocate the target array |
| 1141 | 129 | cxstring* lines; |
|
1168
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
130 | size_t lc = cx_strsplit_a( |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
131 | pool->allocator, contentstr, cx_str("\n"), SIZE_MAX, &lines |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
132 | ); |
| 1141 | 133 | |
| 134 | // skip the header and parse the remaining data into a linked list | |
|
1168
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
135 | // the nodes of the list shall also be allocated by the pool |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
136 | CxList* datalist = cxLinkedListCreate( |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
137 | pool->allocator, NULL, sizeof(CSVData) |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
138 | ); |
| 1141 | 139 | for (size_t i = 1 ; i < lc ; i++) { |
| 140 | if (lines[i].length == 0) continue; | |
| 141 | cxstring fields[3]; | |
|
1168
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
142 | size_t fc = cx_strsplit(lines[i], cx_str(";"), 3, fields); |
| 1141 | 143 | if (fc != 3) { |
| 144 | fprintf(stderr, "Syntax error in line %zu.\n", i); | |
| 145 | cxMempoolFree(pool); | |
| 146 | return 1; | |
| 147 | } | |
| 148 | CSVData data; | |
| 149 | data.column_a = fields[0]; | |
| 150 | data.column_b = fields[1]; | |
| 151 | data.column_c = fields[2]; | |
| 152 | cxListAdd(datalist, &data); | |
| 153 | } | |
| 154 | ||
| 155 | // iterate through the list and output the data | |
| 156 | CxIterator iter = cxListIterator(datalist); | |
| 157 | cx_foreach(CSVData*, data, iter) { | |
|
1298
0597f1f20ea9
use new string formatting macros in documentation
Mike Becker <universe@uap-core.de>
parents:
1283
diff
changeset
|
158 | printf("Column A: %" CX_PRIstr " | " |
|
0597f1f20ea9
use new string formatting macros in documentation
Mike Becker <universe@uap-core.de>
parents:
1283
diff
changeset
|
159 | "Column B: %" CX_PRIstr " | " |
|
0597f1f20ea9
use new string formatting macros in documentation
Mike Becker <universe@uap-core.de>
parents:
1283
diff
changeset
|
160 | "Column C: %" CX_PRIstr "\n", |
|
0597f1f20ea9
use new string formatting macros in documentation
Mike Becker <universe@uap-core.de>
parents:
1283
diff
changeset
|
161 | CX_SFMT(data->column_a), |
|
0597f1f20ea9
use new string formatting macros in documentation
Mike Becker <universe@uap-core.de>
parents:
1283
diff
changeset
|
162 | CX_SFMT(data->column_b), |
|
0597f1f20ea9
use new string formatting macros in documentation
Mike Becker <universe@uap-core.de>
parents:
1283
diff
changeset
|
163 | CX_SFMT(data->column_c) |
| 1141 | 164 | ); |
| 165 | } | |
| 166 | ||
| 167 | // cleanup everything, no manual free() needed | |
| 168 | cxMempoolFree(pool); | |
| 169 | ||
| 170 | return 0; | |
| 171 | } | |
| 172 | ``` | |
| 173 | ||
|
1168
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
174 | <seealso> |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
175 | <category ref="apidoc"> |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
176 | <a href="https://ucx.sourceforge.io/api/mempool_8h.html">mempool.h</a> |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
177 | </category> |
|
d92124c8db73
add mempool documentation
Mike Becker <universe@uap-core.de>
parents:
1146
diff
changeset
|
178 | </seealso> |