Improve opool
* include/mailutils/opool.h (mu_opool_detach): New proto. * libmailutils/base/opool.c (mu_opool_bucket): Redo as union to ensure proper alignment. All uses changed. (mu_opool_detach): New function.
Showing
2 changed files
with
94 additions
and
56 deletions
... | @@ -79,13 +79,23 @@ size_t mu_opool_copy (mu_opool_t opool, void *buf, size_t size); | ... | @@ -79,13 +79,23 @@ size_t mu_opool_copy (mu_opool_t opool, void *buf, size_t size); |
79 | If PSIZE is not NULL, store the size of the head chunk to *PSIZE. */ | 79 | If PSIZE is not NULL, store the size of the head chunk to *PSIZE. */ |
80 | void *mu_opool_head (mu_opool_t opool, size_t *psize); | 80 | void *mu_opool_head (mu_opool_t opool, size_t *psize); |
81 | 81 | ||
82 | /* Finish building the object. Equivalent to: | 82 | /* Finishes the object being constructed. Returns pointer to the object, |
83 | and its size in PSIZE (unless it is NULL). | ||
84 | |||
85 | Equivalent to: | ||
83 | mu_opool_coalesce (opool, NULL); | 86 | mu_opool_coalesce (opool, NULL); |
84 | p = mu_opool_head (opool, psize); | 87 | p = mu_opool_head (opool, psize); |
85 | mu_opool_clear (opool); | 88 | mu_opool_clear (opool); |
86 | return p; */ | 89 | return p; */ |
87 | void *mu_opool_finish (mu_opool_t opool, size_t *psize); | 90 | void *mu_opool_finish (mu_opool_t opool, size_t *psize); |
88 | 91 | ||
92 | |||
93 | /* Similar to mu_opool_finish, but also detaches the created object from the | ||
94 | pool, so that the latter can be destroyed without affecting the object. | ||
95 | The returned pointer should be deallocated with free(3) when no longer | ||
96 | needed. */ | ||
97 | void *mu_opool_detach (mu_opool_t opool, size_t *psize); | ||
98 | |||
89 | /* Append SIZE bytes from DATA to the pool and return the pointer to the | 99 | /* Append SIZE bytes from DATA to the pool and return the pointer to the |
90 | created object. */ | 100 | created object. */ |
91 | void *mu_opool_dup (mu_opool_t pool, void const *data, size_t size); | 101 | void *mu_opool_dup (mu_opool_t pool, void const *data, size_t size); | ... | ... |
... | @@ -22,6 +22,7 @@ | ... | @@ -22,6 +22,7 @@ |
22 | #endif | 22 | #endif |
23 | #include <stdio.h> | 23 | #include <stdio.h> |
24 | #include <stdlib.h> | 24 | #include <stdlib.h> |
25 | #include <stdint.h> | ||
25 | #include <string.h> | 26 | #include <string.h> |
26 | #include <mailutils/types.h> | 27 | #include <mailutils/types.h> |
27 | #include <mailutils/alloc.h> | 28 | #include <mailutils/alloc.h> |
... | @@ -31,27 +32,35 @@ | ... | @@ -31,27 +32,35 @@ |
31 | #include <mailutils/nls.h> | 32 | #include <mailutils/nls.h> |
32 | #include <mailutils/iterator.h> | 33 | #include <mailutils/iterator.h> |
33 | 34 | ||
34 | struct mu_opool_bucket | 35 | struct bucket_header |
35 | { | 36 | { |
36 | struct mu_opool_bucket *next; | 37 | union mu_opool_bucket *next; |
37 | char *buf; | 38 | char *buf; |
38 | size_t level; | 39 | size_t level; |
39 | size_t size; | 40 | size_t size; |
40 | }; | 41 | }; |
41 | 42 | ||
43 | union mu_opool_bucket | ||
44 | { | ||
45 | struct bucket_header hdr; | ||
46 | long double align_double; | ||
47 | uintmax_t align_uintmax; | ||
48 | void *align_ptr; | ||
49 | }; | ||
50 | |||
42 | struct _mu_opool | 51 | struct _mu_opool |
43 | { | 52 | { |
44 | int flags; /* Flag bits */ | 53 | int flags; /* Flag bits */ |
45 | size_t bucket_size; /* Default bucket size */ | 54 | size_t bucket_size; /* Default bucket size */ |
46 | size_t itr_count; /* Number of iterators created for this pool */ | 55 | size_t itr_count; /* Number of iterators created for this pool */ |
47 | struct mu_opool_bucket *bkt_head, *bkt_tail; | 56 | union mu_opool_bucket *bkt_head, *bkt_tail; |
48 | struct mu_opool_bucket *bkt_fini; /* List of finished objects */ | 57 | union mu_opool_bucket *bkt_fini; /* List of finished objects */ |
49 | }; | 58 | }; |
50 | 59 | ||
51 | static struct mu_opool_bucket * | 60 | static union mu_opool_bucket * |
52 | alloc_bucket (struct _mu_opool *opool, size_t size) | 61 | alloc_bucket (struct _mu_opool *opool, size_t size) |
53 | { | 62 | { |
54 | struct mu_opool_bucket *p = malloc (sizeof (*p) + size); | 63 | union mu_opool_bucket *p = malloc (sizeof (*p) + size); |
55 | if (!p) | 64 | if (!p) |
56 | { | 65 | { |
57 | if (opool->flags & MU_OPOOL_ENOMEMABRT) | 66 | if (opool->flags & MU_OPOOL_ENOMEMABRT) |
... | @@ -59,10 +68,10 @@ alloc_bucket (struct _mu_opool *opool, size_t size) | ... | @@ -59,10 +68,10 @@ alloc_bucket (struct _mu_opool *opool, size_t size) |
59 | } | 68 | } |
60 | else | 69 | else |
61 | { | 70 | { |
62 | p->buf = (char*)(p + 1); | 71 | p->hdr.buf = (char*)(p + 1); |
63 | p->level = 0; | 72 | p->hdr.level = 0; |
64 | p->size = size; | 73 | p->hdr.size = size; |
65 | p->next = NULL; | 74 | p->hdr.next = NULL; |
66 | } | 75 | } |
67 | return p; | 76 | return p; |
68 | } | 77 | } |
... | @@ -70,11 +79,11 @@ alloc_bucket (struct _mu_opool *opool, size_t size) | ... | @@ -70,11 +79,11 @@ alloc_bucket (struct _mu_opool *opool, size_t size) |
70 | static int | 79 | static int |
71 | alloc_pool (mu_opool_t opool, size_t size) | 80 | alloc_pool (mu_opool_t opool, size_t size) |
72 | { | 81 | { |
73 | struct mu_opool_bucket *p = alloc_bucket (opool, opool->bucket_size); | 82 | union mu_opool_bucket *p = alloc_bucket (opool, opool->bucket_size); |
74 | if (!p) | 83 | if (!p) |
75 | return ENOMEM; | 84 | return ENOMEM; |
76 | if (opool->bkt_tail) | 85 | if (opool->bkt_tail) |
77 | opool->bkt_tail->next = p; | 86 | opool->bkt_tail->hdr.next = p; |
78 | else | 87 | else |
79 | opool->bkt_head = p; | 88 | opool->bkt_head = p; |
80 | opool->bkt_tail = p; | 89 | opool->bkt_tail = p; |
... | @@ -86,14 +95,15 @@ copy_chars (mu_opool_t opool, const char *str, size_t n, size_t *psize) | ... | @@ -86,14 +95,15 @@ copy_chars (mu_opool_t opool, const char *str, size_t n, size_t *psize) |
86 | { | 95 | { |
87 | size_t rest; | 96 | size_t rest; |
88 | 97 | ||
89 | if (!opool->bkt_head || opool->bkt_tail->level == opool->bkt_tail->size) | 98 | if (!opool->bkt_head |
99 | || opool->bkt_tail->hdr.level == opool->bkt_tail->hdr.size) | ||
90 | if (alloc_pool (opool, opool->bucket_size)) | 100 | if (alloc_pool (opool, opool->bucket_size)) |
91 | return ENOMEM; | 101 | return ENOMEM; |
92 | rest = opool->bkt_tail->size - opool->bkt_tail->level; | 102 | rest = opool->bkt_tail->hdr.size - opool->bkt_tail->hdr.level; |
93 | if (n > rest) | 103 | if (n > rest) |
94 | n = rest; | 104 | n = rest; |
95 | memcpy (opool->bkt_tail->buf + opool->bkt_tail->level, str, n); | 105 | memcpy (opool->bkt_tail->hdr.buf + opool->bkt_tail->hdr.level, str, n); |
96 | opool->bkt_tail->level += n; | 106 | opool->bkt_tail->hdr.level += n; |
97 | *psize = n; | 107 | *psize = n; |
98 | return 0; | 108 | return 0; |
99 | } | 109 | } |
... | @@ -142,7 +152,7 @@ mu_opool_clear (mu_opool_t opool) | ... | @@ -142,7 +152,7 @@ mu_opool_clear (mu_opool_t opool) |
142 | 152 | ||
143 | if (opool->bkt_tail) | 153 | if (opool->bkt_tail) |
144 | { | 154 | { |
145 | opool->bkt_tail->next = opool->bkt_fini; | 155 | opool->bkt_tail->hdr.next = opool->bkt_fini; |
146 | opool->bkt_fini = opool->bkt_head; | 156 | opool->bkt_fini = opool->bkt_head; |
147 | opool->bkt_head = opool->bkt_tail = NULL; | 157 | opool->bkt_head = opool->bkt_tail = NULL; |
148 | } | 158 | } |
... | @@ -151,14 +161,14 @@ mu_opool_clear (mu_opool_t opool) | ... | @@ -151,14 +161,14 @@ mu_opool_clear (mu_opool_t opool) |
151 | void | 161 | void |
152 | mu_opool_destroy (mu_opool_t *popool) | 162 | mu_opool_destroy (mu_opool_t *popool) |
153 | { | 163 | { |
154 | struct mu_opool_bucket *p; | 164 | union mu_opool_bucket *p; |
155 | if (popool && *popool) | 165 | if (popool && *popool) |
156 | { | 166 | { |
157 | mu_opool_t opool = *popool; | 167 | mu_opool_t opool = *popool; |
158 | mu_opool_clear (opool); | 168 | mu_opool_clear (opool); |
159 | for (p = opool->bkt_fini; p; ) | 169 | for (p = opool->bkt_fini; p; ) |
160 | { | 170 | { |
161 | struct mu_opool_bucket *next = p->next; | 171 | union mu_opool_bucket *next = p->hdr.next; |
162 | free (p); | 172 | free (p); |
163 | p = next; | 173 | p = next; |
164 | } | 174 | } |
... | @@ -174,13 +184,14 @@ mu_opool_alloc (mu_opool_t opool, size_t size) | ... | @@ -174,13 +184,14 @@ mu_opool_alloc (mu_opool_t opool, size_t size) |
174 | { | 184 | { |
175 | size_t rest; | 185 | size_t rest; |
176 | 186 | ||
177 | if (!opool->bkt_head || opool->bkt_tail->level == opool->bkt_tail->size) | 187 | if (!opool->bkt_head |
188 | || opool->bkt_tail->hdr.level == opool->bkt_tail->hdr.size) | ||
178 | if (alloc_pool (opool, opool->bucket_size)) | 189 | if (alloc_pool (opool, opool->bucket_size)) |
179 | return ENOMEM; | 190 | return ENOMEM; |
180 | rest = opool->bkt_tail->size - opool->bkt_tail->level; | 191 | rest = opool->bkt_tail->hdr.size - opool->bkt_tail->hdr.level; |
181 | if (size < rest) | 192 | if (size < rest) |
182 | rest = size; | 193 | rest = size; |
183 | opool->bkt_tail->level += rest; | 194 | opool->bkt_tail->hdr.level += rest; |
184 | size -= rest; | 195 | size -= rest; |
185 | } | 196 | } |
186 | return 0; | 197 | return 0; |
... | @@ -217,9 +228,9 @@ size_t | ... | @@ -217,9 +228,9 @@ size_t |
217 | mu_opool_size (mu_opool_t opool) | 228 | mu_opool_size (mu_opool_t opool) |
218 | { | 229 | { |
219 | size_t size = 0; | 230 | size_t size = 0; |
220 | struct mu_opool_bucket *p; | 231 | union mu_opool_bucket *p; |
221 | for (p = opool->bkt_head; p; p = p->next) | 232 | for (p = opool->bkt_head; p; p = p->hdr.next) |
222 | size += p->level; | 233 | size += p->hdr.level; |
223 | return size; | 234 | return size; |
224 | } | 235 | } |
225 | 236 | ||
... | @@ -228,14 +239,14 @@ mu_opool_copy (mu_opool_t opool, void *buf, size_t size) | ... | @@ -228,14 +239,14 @@ mu_opool_copy (mu_opool_t opool, void *buf, size_t size) |
228 | { | 239 | { |
229 | char *cp = buf; | 240 | char *cp = buf; |
230 | size_t total = 0; | 241 | size_t total = 0; |
231 | struct mu_opool_bucket *p; | 242 | union mu_opool_bucket *p; |
232 | 243 | ||
233 | for (p = opool->bkt_head; p && total < size; p = p->next) | 244 | for (p = opool->bkt_head; p && total < size; p = p->hdr.next) |
234 | { | 245 | { |
235 | size_t cpsize = size - total; | 246 | size_t cpsize = size - total; |
236 | if (cpsize > p->level) | 247 | if (cpsize > p->hdr.level) |
237 | cpsize = p->level; | 248 | cpsize = p->hdr.level; |
238 | memcpy (cp, p->buf, cpsize); | 249 | memcpy (cp, p->hdr.buf, cpsize); |
239 | cp += cpsize; | 250 | cp += cpsize; |
240 | total += cpsize; | 251 | total += cpsize; |
241 | } | 252 | } |
... | @@ -249,12 +260,12 @@ mu_opool_coalesce (mu_opool_t opool, size_t *psize) | ... | @@ -249,12 +260,12 @@ mu_opool_coalesce (mu_opool_t opool, size_t *psize) |
249 | 260 | ||
250 | if (opool->itr_count) | 261 | if (opool->itr_count) |
251 | return MU_ERR_FAILURE; | 262 | return MU_ERR_FAILURE; |
252 | if (opool->bkt_head && opool->bkt_head->next == NULL) | 263 | if (opool->bkt_head && opool->bkt_head->hdr.next == NULL) |
253 | size = opool->bkt_head->level; | 264 | size = opool->bkt_head->hdr.level; |
254 | else | 265 | else |
255 | { | 266 | { |
256 | struct mu_opool_bucket *bucket; | 267 | union mu_opool_bucket *bucket; |
257 | struct mu_opool_bucket *p; | 268 | union mu_opool_bucket *p; |
258 | 269 | ||
259 | size = mu_opool_size (opool); | 270 | size = mu_opool_size (opool); |
260 | 271 | ||
... | @@ -263,9 +274,10 @@ mu_opool_coalesce (mu_opool_t opool, size_t *psize) | ... | @@ -263,9 +274,10 @@ mu_opool_coalesce (mu_opool_t opool, size_t *psize) |
263 | return ENOMEM; | 274 | return ENOMEM; |
264 | for (p = opool->bkt_head; p; ) | 275 | for (p = opool->bkt_head; p; ) |
265 | { | 276 | { |
266 | struct mu_opool_bucket *next = p->next; | 277 | union mu_opool_bucket *next = p->hdr.next; |
267 | memcpy (bucket->buf + bucket->level, p->buf, p->level); | 278 | memcpy (bucket->hdr.buf + bucket->hdr.level, p->hdr.buf, |
268 | bucket->level += p->level; | 279 | p->hdr.level); |
280 | bucket->hdr.level += p->hdr.level; | ||
269 | free (p); | 281 | free (p); |
270 | p = next; | 282 | p = next; |
271 | } | 283 | } |
... | @@ -280,8 +292,8 @@ void * | ... | @@ -280,8 +292,8 @@ void * |
280 | mu_opool_head (mu_opool_t opool, size_t *psize) | 292 | mu_opool_head (mu_opool_t opool, size_t *psize) |
281 | { | 293 | { |
282 | if (psize) | 294 | if (psize) |
283 | *psize = opool->bkt_head ? opool->bkt_head->level : 0; | 295 | *psize = opool->bkt_head ? opool->bkt_head->hdr.level : 0; |
284 | return opool->bkt_head ? opool->bkt_head->buf : NULL; | 296 | return opool->bkt_head ? opool->bkt_head->hdr.buf : NULL; |
285 | } | 297 | } |
286 | 298 | ||
287 | void * | 299 | void * |
... | @@ -290,7 +302,22 @@ mu_opool_finish (mu_opool_t opool, size_t *psize) | ... | @@ -290,7 +302,22 @@ mu_opool_finish (mu_opool_t opool, size_t *psize) |
290 | if (mu_opool_coalesce (opool, psize)) | 302 | if (mu_opool_coalesce (opool, psize)) |
291 | return NULL; | 303 | return NULL; |
292 | mu_opool_clear (opool); | 304 | mu_opool_clear (opool); |
293 | return opool->bkt_fini->buf; | 305 | return opool->bkt_fini->hdr.buf; |
306 | } | ||
307 | |||
308 | void * | ||
309 | mu_opool_detach (mu_opool_t opool, size_t *psize) | ||
310 | { | ||
311 | union mu_opool_bucket *bp; | ||
312 | |||
313 | if (mu_opool_coalesce (opool, psize)) | ||
314 | return NULL; | ||
315 | mu_opool_clear (opool); | ||
316 | |||
317 | bp = opool->bkt_fini; | ||
318 | opool->bkt_fini = bp->hdr.next; | ||
319 | memmove (bp, bp->hdr.buf, bp->hdr.level); | ||
320 | return bp; | ||
294 | } | 321 | } |
295 | 322 | ||
296 | void | 323 | void |
... | @@ -304,24 +331,25 @@ mu_opool_free (mu_opool_t pool, void *obj) | ... | @@ -304,24 +331,25 @@ mu_opool_free (mu_opool_t pool, void *obj) |
304 | mu_opool_finish (pool, NULL); | 331 | mu_opool_finish (pool, NULL); |
305 | while (pool->bkt_fini) | 332 | while (pool->bkt_fini) |
306 | { | 333 | { |
307 | struct mu_opool_bucket *next = pool->bkt_fini->next; | 334 | union mu_opool_bucket *next = pool->bkt_fini->hdr.next; |
308 | free (pool->bkt_fini); | 335 | free (pool->bkt_fini); |
309 | pool->bkt_fini = next; | 336 | pool->bkt_fini = next; |
310 | } | 337 | } |
311 | } | 338 | } |
312 | else | 339 | else |
313 | { | 340 | { |
314 | struct mu_opool_bucket *bucket = pool->bkt_fini, **pprev = &pool->bkt_fini; | 341 | union mu_opool_bucket *bucket = pool->bkt_fini, |
342 | **pprev = &pool->bkt_fini; | ||
315 | while (bucket) | 343 | while (bucket) |
316 | { | 344 | { |
317 | if (bucket->buf == obj) | 345 | if (bucket->hdr.buf == obj) |
318 | { | 346 | { |
319 | *pprev = bucket->next; | 347 | *pprev = bucket->hdr.next; |
320 | free (bucket); | 348 | free (bucket); |
321 | return; | 349 | return; |
322 | } | 350 | } |
323 | pprev = &bucket->next; | 351 | pprev = &bucket->hdr.next; |
324 | bucket = bucket->next; | 352 | bucket = bucket->hdr.next; |
325 | } | 353 | } |
326 | } | 354 | } |
327 | } | 355 | } |
... | @@ -357,18 +385,18 @@ mu_opool_union (mu_opool_t *pdst, mu_opool_t *psrc) | ... | @@ -357,18 +385,18 @@ mu_opool_union (mu_opool_t *pdst, mu_opool_t *psrc) |
357 | dst = *pdst; | 385 | dst = *pdst; |
358 | 386 | ||
359 | if (dst->bkt_tail) | 387 | if (dst->bkt_tail) |
360 | dst->bkt_tail->next = src->bkt_head; | 388 | dst->bkt_tail->hdr.next = src->bkt_head; |
361 | else | 389 | else |
362 | dst->bkt_head = src->bkt_head; | 390 | dst->bkt_head = src->bkt_head; |
363 | dst->bkt_tail = src->bkt_tail; | 391 | dst->bkt_tail = src->bkt_tail; |
364 | 392 | ||
365 | if (src->bkt_fini) | 393 | if (src->bkt_fini) |
366 | { | 394 | { |
367 | struct mu_opool_bucket *p; | 395 | union mu_opool_bucket *p; |
368 | 396 | ||
369 | for (p = src->bkt_fini; p->next; p = p->next) | 397 | for (p = src->bkt_fini; p->hdr.next; p = p->hdr.next) |
370 | ; | 398 | ; |
371 | p->next = dst->bkt_fini; | 399 | p->hdr.next = dst->bkt_fini; |
372 | dst->bkt_fini = src->bkt_fini; | 400 | dst->bkt_fini = src->bkt_fini; |
373 | } | 401 | } |
374 | 402 | ||
... | @@ -382,7 +410,7 @@ mu_opool_union (mu_opool_t *pdst, mu_opool_t *psrc) | ... | @@ -382,7 +410,7 @@ mu_opool_union (mu_opool_t *pdst, mu_opool_t *psrc) |
382 | struct opool_iterator | 410 | struct opool_iterator |
383 | { | 411 | { |
384 | mu_opool_t opool; | 412 | mu_opool_t opool; |
385 | struct mu_opool_bucket *cur; | 413 | union mu_opool_bucket *cur; |
386 | }; | 414 | }; |
387 | 415 | ||
388 | static int | 416 | static int |
... | @@ -399,7 +427,7 @@ opitr_next (void *owner) | ... | @@ -399,7 +427,7 @@ opitr_next (void *owner) |
399 | struct opool_iterator *itr = owner; | 427 | struct opool_iterator *itr = owner; |
400 | if (itr->cur) | 428 | if (itr->cur) |
401 | { | 429 | { |
402 | itr->cur = itr->cur->next; | 430 | itr->cur = itr->cur->hdr.next; |
403 | return 0; | 431 | return 0; |
404 | } | 432 | } |
405 | return EINVAL; | 433 | return EINVAL; |
... | @@ -412,9 +440,9 @@ opitr_getitem (void *owner, void **pret, const void **pkey) | ... | @@ -412,9 +440,9 @@ opitr_getitem (void *owner, void **pret, const void **pkey) |
412 | if (!itr->cur) | 440 | if (!itr->cur) |
413 | return MU_ERR_NOENT; | 441 | return MU_ERR_NOENT; |
414 | 442 | ||
415 | *pret = itr->cur->buf; | 443 | *pret = itr->cur->hdr.buf; |
416 | if (pkey) | 444 | if (pkey) |
417 | *(size_t*) pkey = itr->cur->level; | 445 | *(size_t*) pkey = itr->cur->hdr.level; |
418 | return 0; | 446 | return 0; |
419 | } | 447 | } |
420 | 448 | ||
... | @@ -429,7 +457,7 @@ static int | ... | @@ -429,7 +457,7 @@ static int |
429 | opitr_delitem (void *owner, void *item) | 457 | opitr_delitem (void *owner, void *item) |
430 | { | 458 | { |
431 | struct opool_iterator *itr = owner; | 459 | struct opool_iterator *itr = owner; |
432 | return (itr->cur && itr->cur->buf == item) ? | 460 | return (itr->cur && itr->cur->hdr.buf == item) ? |
433 | MU_ITR_DELITEM_NEXT : MU_ITR_DELITEM_NOTHING; | 461 | MU_ITR_DELITEM_NEXT : MU_ITR_DELITEM_NOTHING; |
434 | } | 462 | } |
435 | 463 | ... | ... |
-
Please register or sign in to post a comment