Commit 3d7a66ae 3d7a66aeb49cadc0f4faffa465ef994539629aa9 by Sergey Poznyakoff

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.
1 parent e2bd3a05
...@@ -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
......