49 if (pool->capacity > newcap || cx_szmul(newcap, |
49 if (pool->capacity > newcap || cx_szmul(newcap, |
50 sizeof(struct cx_mempool_memory_s*), &newmsize)) { |
50 sizeof(struct cx_mempool_memory_s*), &newmsize)) { |
51 errno = EOVERFLOW; |
51 errno = EOVERFLOW; |
52 return 1; |
52 return 1; |
53 } |
53 } |
54 struct cx_mempool_memory_s **newdata = realloc(pool->data, newmsize); |
54 struct cx_mempool_memory_s **newdata = cxRealloc( |
|
55 cxDefaultAllocator, pool->data, newmsize); |
55 if (newdata == NULL) return 1; |
56 if (newdata == NULL) return 1; |
56 pool->data = newdata; |
57 pool->data = newdata; |
57 pool->capacity = newcap; |
58 pool->capacity = newcap; |
58 return 0; |
59 return 0; |
59 } |
60 } |
66 |
67 |
67 if (cx_mempool_ensure_capacity(pool, pool->size + 1)) { |
68 if (cx_mempool_ensure_capacity(pool, pool->size + 1)) { |
68 return NULL; |
69 return NULL; |
69 } |
70 } |
70 |
71 |
71 struct cx_mempool_memory_s *mem = malloc(sizeof(cx_destructor_func) + n); |
72 struct cx_mempool_memory_s *mem = cxMalloc( |
|
73 cxDefaultAllocator, sizeof(cx_destructor_func) + n); |
72 if (mem == NULL) return NULL; |
74 if (mem == NULL) return NULL; |
73 |
75 |
74 mem->destructor = pool->auto_destr; |
76 mem->destructor = pool->auto_destr; |
75 pool->data[pool->size] = mem; |
77 pool->data[pool->size] = mem; |
76 pool->size++; |
78 pool->size++; |
101 ) { |
103 ) { |
102 struct cx_mempool_s *pool = p; |
104 struct cx_mempool_s *pool = p; |
103 |
105 |
104 struct cx_mempool_memory_s *mem, *newm; |
106 struct cx_mempool_memory_s *mem, *newm; |
105 mem = (struct cx_mempool_memory_s*)(((char *) ptr) - sizeof(cx_destructor_func)); |
107 mem = (struct cx_mempool_memory_s*)(((char *) ptr) - sizeof(cx_destructor_func)); |
106 newm = realloc(mem, n + sizeof(cx_destructor_func)); |
108 newm = cxRealloc(cxDefaultAllocator, mem, n + sizeof(cx_destructor_func)); |
107 |
109 |
108 if (newm == NULL) return NULL; |
110 if (newm == NULL) return NULL; |
109 if (mem != newm) { |
111 if (mem != newm) { |
110 for (size_t i = 0; i < pool->size; i++) { |
112 for (size_t i = 0; i < pool->size; i++) { |
111 if (pool->data[i] == mem) { |
113 if (pool->data[i] == mem) { |
132 for (size_t i = 0; i < pool->size; i++) { |
134 for (size_t i = 0; i < pool->size; i++) { |
133 if (mem == pool->data[i]) { |
135 if (mem == pool->data[i]) { |
134 if (mem->destructor) { |
136 if (mem->destructor) { |
135 mem->destructor(mem->c); |
137 mem->destructor(mem->c); |
136 } |
138 } |
137 free(mem); |
139 cxFree(cxDefaultAllocator, mem); |
138 size_t last_index = pool->size - 1; |
140 size_t last_index = pool->size - 1; |
139 if (i != last_index) { |
141 if (i != last_index) { |
140 pool->data[i] = pool->data[last_index]; |
142 pool->data[i] = pool->data[last_index]; |
141 pool->data[last_index] = NULL; |
143 pool->data[last_index] = NULL; |
142 } |
144 } |
153 for (size_t i = 0; i < pool->size; i++) { |
155 for (size_t i = 0; i < pool->size; i++) { |
154 mem = pool->data[i]; |
156 mem = pool->data[i]; |
155 if (mem->destructor) { |
157 if (mem->destructor) { |
156 mem->destructor(mem->c); |
158 mem->destructor(mem->c); |
157 } |
159 } |
158 free(mem); |
160 cxFree(cxDefaultAllocator, mem); |
159 } |
161 } |
160 free(pool->data); |
162 cxFree(cxDefaultAllocator, pool->data); |
161 free((void*) pool->allocator); |
163 cxFree(cxDefaultAllocator, (void*) pool->allocator); |
162 free(pool); |
164 cxFree(cxDefaultAllocator, pool); |
163 } |
165 } |
164 |
166 |
165 void cxMempoolSetDestructor( |
167 void cxMempoolSetDestructor( |
166 void *ptr, |
168 void *ptr, |
167 cx_destructor_func func |
169 cx_destructor_func func |
217 errno = EOVERFLOW; |
219 errno = EOVERFLOW; |
218 return NULL; |
220 return NULL; |
219 } |
221 } |
220 |
222 |
221 struct cx_mempool_s *pool = |
223 struct cx_mempool_s *pool = |
222 malloc(sizeof(struct cx_mempool_s)); |
224 cxMalloc(cxDefaultAllocator, sizeof(struct cx_mempool_s)); |
223 if (pool == NULL) return NULL; |
225 if (pool == NULL) return NULL; |
224 |
226 |
225 CxAllocator *provided_allocator = malloc(sizeof(CxAllocator)); |
227 CxAllocator *provided_allocator = cxMalloc(cxDefaultAllocator, sizeof(CxAllocator)); |
226 if (provided_allocator == NULL) { // LCOV_EXCL_START |
228 if (provided_allocator == NULL) { // LCOV_EXCL_START |
227 free(pool); |
229 cxFree(cxDefaultAllocator, pool); |
228 return NULL; |
230 return NULL; |
229 } // LCOV_EXCL_STOP |
231 } // LCOV_EXCL_STOP |
230 provided_allocator->cl = &cx_mempool_allocator_class; |
232 provided_allocator->cl = &cx_mempool_allocator_class; |
231 provided_allocator->data = pool; |
233 provided_allocator->data = pool; |
232 |
234 |
233 pool->allocator = provided_allocator; |
235 pool->allocator = provided_allocator; |
234 |
236 |
235 pool->data = malloc(poolsize); |
237 pool->data = cxMalloc(cxDefaultAllocator, poolsize); |
236 if (pool->data == NULL) { // LCOV_EXCL_START |
238 if (pool->data == NULL) { // LCOV_EXCL_START |
237 free(provided_allocator); |
239 cxFree(cxDefaultAllocator, provided_allocator); |
238 free(pool); |
240 cxFree(cxDefaultAllocator, pool); |
239 return NULL; |
241 return NULL; |
240 } // LCOV_EXCL_STOP |
242 } // LCOV_EXCL_STOP |
241 |
243 |
242 pool->size = 0; |
244 pool->size = 0; |
243 pool->capacity = capacity; |
245 pool->capacity = capacity; |
244 pool->auto_destr = destr; |
246 pool->auto_destr = destr; |
245 |
247 |
246 return pool; |
248 return pool; |
247 } |
249 } |
248 |
250 |
|
251 static void cx_mempool_free_transferred_allocator(void *al) { |
|
252 cxFree(cxDefaultAllocator, al); |
|
253 } |
|
254 |
249 int cxMempoolTransfer( |
255 int cxMempoolTransfer( |
250 CxMempool *source, |
256 CxMempool *source, |
251 CxMempool *dest |
257 CxMempool *dest |
252 ) { |
258 ) { |
253 // safety check |
259 // safety check |
257 if (cx_mempool_ensure_capacity(dest, dest->size + source->size + 1)) { |
263 if (cx_mempool_ensure_capacity(dest, dest->size + source->size + 1)) { |
258 return 1; // LCOV_EXCL_LINE |
264 return 1; // LCOV_EXCL_LINE |
259 } |
265 } |
260 |
266 |
261 // allocate a replacement allocator for the source pool |
267 // allocate a replacement allocator for the source pool |
262 CxAllocator *new_source_allocator = malloc(sizeof(CxAllocator)); |
268 CxAllocator *new_source_allocator = cxMalloc(cxDefaultAllocator, sizeof(CxAllocator)); |
263 if (new_source_allocator == NULL) { // LCOV_EXCL_START |
269 if (new_source_allocator == NULL) { // LCOV_EXCL_START |
264 return 1; |
270 return 1; |
265 } // LCOV_EXCL_STOP |
271 } // LCOV_EXCL_STOP |
266 new_source_allocator->cl = &cx_mempool_allocator_class; |
272 new_source_allocator->cl = &cx_mempool_allocator_class; |
267 new_source_allocator->data = source; |
273 new_source_allocator->data = source; |
272 |
278 |
273 // register the old allocator with the new pool |
279 // register the old allocator with the new pool |
274 // we have to remove const-ness for this, but that's okay here |
280 // we have to remove const-ness for this, but that's okay here |
275 CxAllocator *transferred_allocator = (CxAllocator*) source->allocator; |
281 CxAllocator *transferred_allocator = (CxAllocator*) source->allocator; |
276 transferred_allocator->data = dest; |
282 transferred_allocator->data = dest; |
277 cxMempoolRegister(dest, transferred_allocator, free); |
283 cxMempoolRegister(dest, transferred_allocator, cx_mempool_free_transferred_allocator); |
278 |
284 |
279 // prepare the source pool for re-use |
285 // prepare the source pool for re-use |
280 source->allocator = new_source_allocator; |
286 source->allocator = new_source_allocator; |
281 memset(source->data, 0, source->size * sizeof(source->data[0])); |
287 memset(source->data, 0, source->size * sizeof(source->data[0])); |
282 source->size = 0; |
288 source->size = 0; |