34 #endif |
34 #endif |
35 #include <inttypes.h> |
35 #include <inttypes.h> |
36 |
36 |
37 #include "mempool.h" |
37 #include "mempool.h" |
38 |
38 |
|
39 /** Capsule for destructible memory chunks. */ |
39 typedef struct { |
40 typedef struct { |
|
41 /** The destructor for the memory chunk. */ |
40 ucx_destructor destructor; |
42 ucx_destructor destructor; |
|
43 /** |
|
44 * First byte of the memory chunk. |
|
45 * Note, that the address <code>&c</code> is also the address |
|
46 * of the whole memory chunk. |
|
47 */ |
41 char c; |
48 char c; |
42 } ucx_memchunk; |
49 } ucx_memchunk; |
43 |
50 |
|
51 /** Capsule for data and its destructor. */ |
44 typedef struct { |
52 typedef struct { |
|
53 /** The destructor for the data. */ |
45 ucx_destructor destructor; |
54 ucx_destructor destructor; |
|
55 /** A pointer to the data. */ |
46 void *ptr; |
56 void *ptr; |
47 } ucx_regdestr; |
57 } ucx_regdestr; |
48 |
58 |
49 UCX_EXTERN void ucx_mempool_shared_destr(void* ptr) { |
59 UCX_EXTERN void ucx_mempool_shared_destr(void* ptr) { |
50 ucx_regdestr *rd = (ucx_regdestr*)ptr; |
60 ucx_regdestr *rd = (ucx_regdestr*)ptr; |
78 return EXIT_FAILURE; |
88 return EXIT_FAILURE; |
79 } |
89 } |
80 } |
90 } |
81 |
91 |
82 void *ucx_mempool_malloc(UcxMempool *pool, size_t n) { |
92 void *ucx_mempool_malloc(UcxMempool *pool, size_t n) { |
|
93 if (pool->ndata >= pool->size) { |
|
94 // The hard coded 16 is documented for this function and ucx_mempool_new |
|
95 if (ucx_mempool_chcap(pool, pool->size + 16) == EXIT_FAILURE) { |
|
96 return NULL; |
|
97 } |
|
98 } |
|
99 |
83 ucx_memchunk *mem = (ucx_memchunk*)malloc(sizeof(ucx_destructor) + n); |
100 ucx_memchunk *mem = (ucx_memchunk*)malloc(sizeof(ucx_destructor) + n); |
84 if (!mem) { |
101 if (!mem) { |
85 return NULL; |
102 return NULL; |
86 } |
103 } |
87 |
|
88 if (pool->ndata >= pool->size) { |
|
89 // The hard coded 16 is documented for this function and ucx_mempool_new |
|
90 ucx_mempool_chcap(pool, pool->size + 16); |
|
91 } |
|
92 |
104 |
93 mem->destructor = NULL; |
105 mem->destructor = NULL; |
94 pool->data[pool->ndata] = mem; |
106 pool->data[pool->ndata] = mem; |
95 pool->ndata++; |
107 pool->ndata++; |
96 |
108 |
119 return newm + sizeof(ucx_destructor); |
131 return newm + sizeof(ucx_destructor); |
120 } |
132 } |
121 } |
133 } |
122 fprintf(stderr, "FATAL: 0x%08" PRIxPTR" not in mpool 0x%08" PRIxPTR"\n", |
134 fprintf(stderr, "FATAL: 0x%08" PRIxPTR" not in mpool 0x%08" PRIxPTR"\n", |
123 (intptr_t)ptr, (intptr_t)pool); |
135 (intptr_t)ptr, (intptr_t)pool); |
124 exit(1); |
136 exit(EXIT_FAILURE); |
125 } else { |
137 } else { |
126 return newm + sizeof(ucx_destructor); |
138 return newm + sizeof(ucx_destructor); |
127 } |
139 } |
128 } |
140 } |
129 |
141 |
130 void ucx_mempool_free(UcxMempool *pool, void *ptr) { |
142 void ucx_mempool_free(UcxMempool *pool, void *ptr) { |
131 ucx_memchunk *chunk = (ucx_memchunk*)((char*)ptr-sizeof(ucx_destructor)); |
143 ucx_memchunk *chunk = (ucx_memchunk*)((char*)ptr-sizeof(ucx_destructor)); |
132 for(size_t i=0 ; i<pool->ndata ; i++) { |
144 for(size_t i=0 ; i<pool->ndata ; i++) { |
133 if(chunk == pool->data[i]) { |
145 if(chunk == pool->data[i]) { |
134 if(chunk->destructor != NULL) { |
146 if(chunk->destructor != NULL) { |
135 chunk->destructor(&chunk->c); |
147 chunk->destructor(&(chunk->c)); |
136 } |
148 } |
137 free(chunk); |
149 free(chunk); |
138 size_t last_index = pool->ndata - 1; |
150 size_t last_index = pool->ndata - 1; |
139 if(i != last_index) { |
151 if(i != last_index) { |
140 pool->data[i] = pool->data[last_index]; |
152 pool->data[i] = pool->data[last_index]; |
|
153 pool->data[last_index] = NULL; |
141 } |
154 } |
142 pool->ndata--; |
155 pool->ndata--; |
143 return; |
156 return; |
144 } |
157 } |
145 } |
158 } |