ucx/mempool.c

changeset 440
7c4b9cba09ca
parent 187
24ce2c326d85
equal deleted inserted replaced
439:bf7084544cb1 440:7c4b9cba09ca
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
112 static void cx_mempool_free( 112 static void cx_mempool_free(
113 void *p, 113 void *p,
114 void *ptr 114 void *ptr
115 ) { 115 ) {
116 if (!ptr) return;
116 struct cx_mempool_s *pool = p; 117 struct cx_mempool_s *pool = p;
117 118
118 struct cx_mempool_memory_s *mem = (struct cx_mempool_memory_s *) 119 struct cx_mempool_memory_s *mem = (struct cx_mempool_memory_s *)
119 ((char *) ptr - sizeof(cx_destructor_func)); 120 ((char *) ptr - sizeof(cx_destructor_func));
120 121
121 cx_for_n(i, pool->size) { 122 for (size_t i = 0; i < pool->size; i++) {
122 if (mem == pool->data[i]) { 123 if (mem == pool->data[i]) {
123 if (mem->destructor) { 124 if (mem->destructor) {
124 mem->destructor(mem->c); 125 mem->destructor(mem->c);
125 } 126 }
126 free(mem); 127 free(mem);
131 } 132 }
132 pool->size--; 133 pool->size--;
133 return; 134 return;
134 } 135 }
135 } 136 }
136 abort(); 137 abort(); // LCOV_EXCL_LINE
137 } 138 }
138 139
139 void cxMempoolDestroy(CxMempool *pool) { 140 void cxMempoolFree(CxMempool *pool) {
141 if (pool == NULL) return;
140 struct cx_mempool_memory_s *mem; 142 struct cx_mempool_memory_s *mem;
141 cx_for_n(i, pool->size) { 143 for (size_t i = 0; i < pool->size; i++) {
142 mem = pool->data[i]; 144 mem = pool->data[i];
143 if (mem->destructor) { 145 if (mem->destructor) {
144 mem->destructor(mem->c); 146 mem->destructor(mem->c);
145 } 147 }
146 free(mem); 148 free(mem);
153 void cxMempoolSetDestructor( 155 void cxMempoolSetDestructor(
154 void *ptr, 156 void *ptr,
155 cx_destructor_func func 157 cx_destructor_func func
156 ) { 158 ) {
157 *(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;
158 } 164 }
159 165
160 struct cx_mempool_foreign_mem_s { 166 struct cx_mempool_foreign_mem_s {
161 cx_destructor_func destr; 167 cx_destructor_func destr;
162 void* mem; 168 void* mem;
196 size_t capacity, 202 size_t capacity,
197 cx_destructor_func destr 203 cx_destructor_func destr
198 ) { 204 ) {
199 size_t poolsize; 205 size_t poolsize;
200 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;
201 return NULL; 208 return NULL;
202 } 209 }
203 210
204 struct cx_mempool_s *pool = 211 struct cx_mempool_s *pool =
205 malloc(sizeof(struct cx_mempool_s)); 212 malloc(sizeof(struct cx_mempool_s));
206 if (pool == NULL) { 213 if (pool == NULL) return NULL;
207 return NULL;
208 }
209 214
210 CxAllocator *provided_allocator = malloc(sizeof(CxAllocator)); 215 CxAllocator *provided_allocator = malloc(sizeof(CxAllocator));
211 if (provided_allocator == NULL) { 216 if (provided_allocator == NULL) { // LCOV_EXCL_START
212 free(pool); 217 free(pool);
213 return NULL; 218 return NULL;
214 } 219 } // LCOV_EXCL_STOP
215 provided_allocator->cl = &cx_mempool_allocator_class; 220 provided_allocator->cl = &cx_mempool_allocator_class;
216 provided_allocator->data = pool; 221 provided_allocator->data = pool;
217 222
218 pool->allocator = provided_allocator; 223 pool->allocator = provided_allocator;
219 224
220 pool->data = malloc(poolsize); 225 pool->data = malloc(poolsize);
221 if (pool->data == NULL) { 226 if (pool->data == NULL) { // LCOV_EXCL_START
222 free(provided_allocator); 227 free(provided_allocator);
223 free(pool); 228 free(pool);
224 return NULL; 229 return NULL;
225 } 230 } // LCOV_EXCL_STOP
226 231
227 pool->size = 0; 232 pool->size = 0;
228 pool->capacity = capacity; 233 pool->capacity = capacity;
229 pool->auto_destr = destr; 234 pool->auto_destr = destr;
230 235
231 return (CxMempool *) pool; 236 return pool;
232 } 237 }

mercurial