ucx/mempool.c

changeset 101
7b3a3130be44
parent 56
294d5515583a
equal deleted inserted replaced
100:d2bd73d28ff1 101:7b3a3130be44
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 #include "cx/mempool.h" 29 #include "cx/mempool.h"
30 #include "cx/utils.h" 30
31 #include <string.h> 31 #include <string.h>
32 #include <errno.h>
32 33
33 struct cx_mempool_memory_s { 34 struct cx_mempool_memory_s {
34 /** The destructor. */ 35 /** The destructor. */
35 cx_destructor_func destructor; 36 cx_destructor_func destructor;
36 /** The actual memory. */ 37 /** The actual memory. */
43 ) { 44 ) {
44 struct cx_mempool_s *pool = p; 45 struct cx_mempool_s *pool = p;
45 46
46 if (pool->size >= pool->capacity) { 47 if (pool->size >= pool->capacity) {
47 size_t newcap = pool->capacity - (pool->capacity % 16) + 16; 48 size_t newcap = pool->capacity - (pool->capacity % 16) + 16;
48 struct cx_mempool_memory_s **newdata = realloc(pool->data, newcap*sizeof(struct cx_mempool_memory_s*)); 49 size_t newmsize;
49 if (newdata == NULL) { 50 if (pool->capacity > newcap || cx_szmul(newcap,
51 sizeof(struct cx_mempool_memory_s*), &newmsize)) {
52 errno = EOVERFLOW;
50 return NULL; 53 return NULL;
51 } 54 }
55 struct cx_mempool_memory_s **newdata = realloc(pool->data, newmsize);
56 if (newdata == NULL) return NULL;
52 pool->data = newdata; 57 pool->data = newdata;
53 pool->capacity = newcap; 58 pool->capacity = newcap;
54 } 59 }
55 60
56 struct cx_mempool_memory_s *mem = malloc(sizeof(cx_destructor_func) + n); 61 struct cx_mempool_memory_s *mem = malloc(sizeof(cx_destructor_func) + n);
57 if (mem == NULL) { 62 if (mem == NULL) return NULL;
58 return NULL;
59 }
60 63
61 mem->destructor = pool->auto_destr; 64 mem->destructor = pool->auto_destr;
62 pool->data[pool->size] = mem; 65 pool->data[pool->size] = mem;
63 pool->size++; 66 pool->size++;
64 67
70 size_t nelem, 73 size_t nelem,
71 size_t elsize 74 size_t elsize
72 ) { 75 ) {
73 size_t msz; 76 size_t msz;
74 if (cx_szmul(nelem, elsize, &msz)) { 77 if (cx_szmul(nelem, elsize, &msz)) {
78 errno = EOVERFLOW;
75 return NULL; 79 return NULL;
76 } 80 }
77 void *ptr = cx_mempool_malloc(p, msz); 81 void *ptr = cx_mempool_malloc(p, msz);
78 if (ptr == NULL) { 82 if (ptr == NULL) return NULL;
79 return NULL;
80 }
81 memset(ptr, 0, nelem * elsize); 83 memset(ptr, 0, nelem * elsize);
82 return ptr; 84 return ptr;
83 } 85 }
84 86
85 static void *cx_mempool_realloc( 87 static void *cx_mempool_realloc(
91 93
92 struct cx_mempool_memory_s *mem, *newm; 94 struct cx_mempool_memory_s *mem, *newm;
93 mem = (struct cx_mempool_memory_s*)(((char *) ptr) - sizeof(cx_destructor_func)); 95 mem = (struct cx_mempool_memory_s*)(((char *) ptr) - sizeof(cx_destructor_func));
94 newm = realloc(mem, n + sizeof(cx_destructor_func)); 96 newm = realloc(mem, n + sizeof(cx_destructor_func));
95 97
96 if (newm == NULL) { 98 if (newm == NULL) return NULL;
97 return NULL;
98 }
99 if (mem != newm) { 99 if (mem != newm) {
100 cx_for_n(i, pool->size) { 100 for (size_t i = 0; i < pool->size; i++) {
101 if (pool->data[i] == mem) { 101 if (pool->data[i] == mem) {
102 pool->data[i] = newm; 102 pool->data[i] = newm;
103 return ((char*)newm) + sizeof(cx_destructor_func); 103 return ((char*)newm) + sizeof(cx_destructor_func);
104 } 104 }
105 } 105 }
106 abort(); 106 abort(); // LCOV_EXCL_LINE
107 } else { 107 } else {
108 return ptr; 108 return ptr;
109 } 109 }
110 } 110 }
111 111
117 struct cx_mempool_s *pool = p; 117 struct cx_mempool_s *pool = p;
118 118
119 struct cx_mempool_memory_s *mem = (struct cx_mempool_memory_s *) 119 struct cx_mempool_memory_s *mem = (struct cx_mempool_memory_s *)
120 ((char *) ptr - sizeof(cx_destructor_func)); 120 ((char *) ptr - sizeof(cx_destructor_func));
121 121
122 cx_for_n(i, pool->size) { 122 for (size_t i = 0; i < pool->size; i++) {
123 if (mem == pool->data[i]) { 123 if (mem == pool->data[i]) {
124 if (mem->destructor) { 124 if (mem->destructor) {
125 mem->destructor(mem->c); 125 mem->destructor(mem->c);
126 } 126 }
127 free(mem); 127 free(mem);
132 } 132 }
133 pool->size--; 133 pool->size--;
134 return; 134 return;
135 } 135 }
136 } 136 }
137 abort(); 137 abort(); // LCOV_EXCL_LINE
138 } 138 }
139 139
140 void cxMempoolDestroy(CxMempool *pool) { 140 void cxMempoolFree(CxMempool *pool) {
141 if (pool == NULL) return;
141 struct cx_mempool_memory_s *mem; 142 struct cx_mempool_memory_s *mem;
142 cx_for_n(i, pool->size) { 143 for (size_t i = 0; i < pool->size; i++) {
143 mem = pool->data[i]; 144 mem = pool->data[i];
144 if (mem->destructor) { 145 if (mem->destructor) {
145 mem->destructor(mem->c); 146 mem->destructor(mem->c);
146 } 147 }
147 free(mem); 148 free(mem);
154 void cxMempoolSetDestructor( 155 void cxMempoolSetDestructor(
155 void *ptr, 156 void *ptr,
156 cx_destructor_func func 157 cx_destructor_func func
157 ) { 158 ) {
158 *(cx_destructor_func *) ((char *) ptr - sizeof(cx_destructor_func)) = func; 159 *(cx_destructor_func *) ((char *) ptr - sizeof(cx_destructor_func)) = func;
160 }
161
162 void cxMempoolRemoveDestructor(void *ptr) {
163 *(cx_destructor_func *) ((char *) ptr - sizeof(cx_destructor_func)) = NULL;
159 } 164 }
160 165
161 struct cx_mempool_foreign_mem_s { 166 struct cx_mempool_foreign_mem_s {
162 cx_destructor_func destr; 167 cx_destructor_func destr;
163 void* mem; 168 void* mem;
197 size_t capacity, 202 size_t capacity,
198 cx_destructor_func destr 203 cx_destructor_func destr
199 ) { 204 ) {
200 size_t poolsize; 205 size_t poolsize;
201 if (cx_szmul(capacity, sizeof(struct cx_mempool_memory_s*), &poolsize)) { 206 if (cx_szmul(capacity, sizeof(struct cx_mempool_memory_s*), &poolsize)) {
207 errno = EOVERFLOW;
202 return NULL; 208 return NULL;
203 } 209 }
204 210
205 struct cx_mempool_s *pool = 211 struct cx_mempool_s *pool =
206 malloc(sizeof(struct cx_mempool_s)); 212 malloc(sizeof(struct cx_mempool_s));
207 if (pool == NULL) { 213 if (pool == NULL) return NULL;
208 return NULL;
209 }
210 214
211 CxAllocator *provided_allocator = malloc(sizeof(CxAllocator)); 215 CxAllocator *provided_allocator = malloc(sizeof(CxAllocator));
212 if (provided_allocator == NULL) { 216 if (provided_allocator == NULL) { // LCOV_EXCL_START
213 free(pool); 217 free(pool);
214 return NULL; 218 return NULL;
215 } 219 } // LCOV_EXCL_STOP
216 provided_allocator->cl = &cx_mempool_allocator_class; 220 provided_allocator->cl = &cx_mempool_allocator_class;
217 provided_allocator->data = pool; 221 provided_allocator->data = pool;
218 222
219 pool->allocator = provided_allocator; 223 pool->allocator = provided_allocator;
220 224
221 pool->data = malloc(poolsize); 225 pool->data = malloc(poolsize);
222 if (pool->data == NULL) { 226 if (pool->data == NULL) { // LCOV_EXCL_START
223 free(provided_allocator); 227 free(provided_allocator);
224 free(pool); 228 free(pool);
225 return NULL; 229 return NULL;
226 } 230 } // LCOV_EXCL_STOP
227 231
228 pool->size = 0; 232 pool->size = 0;
229 pool->capacity = capacity; 233 pool->capacity = capacity;
230 pool->auto_destr = destr; 234 pool->auto_destr = destr;
231 235
232 return (CxMempool *) pool; 236 return pool;
233 } 237 }

mercurial