diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2016-12-05 08:48:09 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2016-12-05 08:48:09 +0200 |
commit | 3d7a66aeb49cadc0f4faffa465ef994539629aa9 (patch) | |
tree | 754e4eee1f7612d6470b5ed18e6e616a7806c961 | |
parent | e2bd3a059eb8268d156baf59e41909cae1e28297 (diff) | |
download | mailutils-3d7a66aeb49cadc0f4faffa465ef994539629aa9.tar.gz mailutils-3d7a66aeb49cadc0f4faffa465ef994539629aa9.tar.bz2 |
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.
-rw-r--r-- | include/mailutils/opool.h | 12 | ||||
-rw-r--r-- | libmailutils/base/opool.c | 138 |
2 files changed, 94 insertions, 56 deletions
diff --git a/include/mailutils/opool.h b/include/mailutils/opool.h index 63c5a38f2..45fe64f8f 100644 --- a/include/mailutils/opool.h +++ b/include/mailutils/opool.h @@ -79,13 +79,23 @@ size_t mu_opool_copy (mu_opool_t opool, void *buf, size_t size); If PSIZE is not NULL, store the size of the head chunk to *PSIZE. */ void *mu_opool_head (mu_opool_t opool, size_t *psize); -/* Finish building the object. Equivalent to: +/* Finishes the object being constructed. Returns pointer to the object, + and its size in PSIZE (unless it is NULL). + + Equivalent to: mu_opool_coalesce (opool, NULL); p = mu_opool_head (opool, psize); mu_opool_clear (opool); return p; */ void *mu_opool_finish (mu_opool_t opool, size_t *psize); + +/* Similar to mu_opool_finish, but also detaches the created object from the + pool, so that the latter can be destroyed without affecting the object. + The returned pointer should be deallocated with free(3) when no longer + needed. */ +void *mu_opool_detach (mu_opool_t opool, size_t *psize); + /* Append SIZE bytes from DATA to the pool and return the pointer to the created object. */ void *mu_opool_dup (mu_opool_t pool, void const *data, size_t size); diff --git a/libmailutils/base/opool.c b/libmailutils/base/opool.c index 5e19081ac..d6628dda0 100644 --- a/libmailutils/base/opool.c +++ b/libmailutils/base/opool.c @@ -22,6 +22,7 @@ #endif #include <stdio.h> #include <stdlib.h> +#include <stdint.h> #include <string.h> #include <mailutils/types.h> #include <mailutils/alloc.h> @@ -31,27 +32,35 @@ #include <mailutils/nls.h> #include <mailutils/iterator.h> -struct mu_opool_bucket +struct bucket_header { - struct mu_opool_bucket *next; + union mu_opool_bucket *next; char *buf; size_t level; size_t size; }; +union mu_opool_bucket +{ + struct bucket_header hdr; + long double align_double; + uintmax_t align_uintmax; + void *align_ptr; +}; + struct _mu_opool { int flags; /* Flag bits */ size_t bucket_size; /* Default bucket size */ size_t itr_count; /* Number of iterators created for this pool */ - struct mu_opool_bucket *bkt_head, *bkt_tail; - struct mu_opool_bucket *bkt_fini; /* List of finished objects */ + union mu_opool_bucket *bkt_head, *bkt_tail; + union mu_opool_bucket *bkt_fini; /* List of finished objects */ }; -static struct mu_opool_bucket * +static union mu_opool_bucket * alloc_bucket (struct _mu_opool *opool, size_t size) { - struct mu_opool_bucket *p = malloc (sizeof (*p) + size); + union mu_opool_bucket *p = malloc (sizeof (*p) + size); if (!p) { if (opool->flags & MU_OPOOL_ENOMEMABRT) @@ -59,10 +68,10 @@ alloc_bucket (struct _mu_opool *opool, size_t size) } else { - p->buf = (char*)(p + 1); - p->level = 0; - p->size = size; - p->next = NULL; + p->hdr.buf = (char*)(p + 1); + p->hdr.level = 0; + p->hdr.size = size; + p->hdr.next = NULL; } return p; } @@ -70,11 +79,11 @@ alloc_bucket (struct _mu_opool *opool, size_t size) static int alloc_pool (mu_opool_t opool, size_t size) { - struct mu_opool_bucket *p = alloc_bucket (opool, opool->bucket_size); + union mu_opool_bucket *p = alloc_bucket (opool, opool->bucket_size); if (!p) return ENOMEM; if (opool->bkt_tail) - opool->bkt_tail->next = p; + opool->bkt_tail->hdr.next = p; else opool->bkt_head = p; opool->bkt_tail = p; @@ -86,14 +95,15 @@ copy_chars (mu_opool_t opool, const char *str, size_t n, size_t *psize) { size_t rest; - if (!opool->bkt_head || opool->bkt_tail->level == opool->bkt_tail->size) + if (!opool->bkt_head + || opool->bkt_tail->hdr.level == opool->bkt_tail->hdr.size) if (alloc_pool (opool, opool->bucket_size)) return ENOMEM; - rest = opool->bkt_tail->size - opool->bkt_tail->level; + rest = opool->bkt_tail->hdr.size - opool->bkt_tail->hdr.level; if (n > rest) n = rest; - memcpy (opool->bkt_tail->buf + opool->bkt_tail->level, str, n); - opool->bkt_tail->level += n; + memcpy (opool->bkt_tail->hdr.buf + opool->bkt_tail->hdr.level, str, n); + opool->bkt_tail->hdr.level += n; *psize = n; return 0; } @@ -142,7 +152,7 @@ mu_opool_clear (mu_opool_t opool) if (opool->bkt_tail) { - opool->bkt_tail->next = opool->bkt_fini; + opool->bkt_tail->hdr.next = opool->bkt_fini; opool->bkt_fini = opool->bkt_head; opool->bkt_head = opool->bkt_tail = NULL; } @@ -151,14 +161,14 @@ mu_opool_clear (mu_opool_t opool) void mu_opool_destroy (mu_opool_t *popool) { - struct mu_opool_bucket *p; + union mu_opool_bucket *p; if (popool && *popool) { mu_opool_t opool = *popool; mu_opool_clear (opool); for (p = opool->bkt_fini; p; ) { - struct mu_opool_bucket *next = p->next; + union mu_opool_bucket *next = p->hdr.next; free (p); p = next; } @@ -174,13 +184,14 @@ mu_opool_alloc (mu_opool_t opool, size_t size) { size_t rest; - if (!opool->bkt_head || opool->bkt_tail->level == opool->bkt_tail->size) + if (!opool->bkt_head + || opool->bkt_tail->hdr.level == opool->bkt_tail->hdr.size) if (alloc_pool (opool, opool->bucket_size)) return ENOMEM; - rest = opool->bkt_tail->size - opool->bkt_tail->level; + rest = opool->bkt_tail->hdr.size - opool->bkt_tail->hdr.level; if (size < rest) rest = size; - opool->bkt_tail->level += rest; + opool->bkt_tail->hdr.level += rest; size -= rest; } return 0; @@ -217,9 +228,9 @@ size_t mu_opool_size (mu_opool_t opool) { size_t size = 0; - struct mu_opool_bucket *p; - for (p = opool->bkt_head; p; p = p->next) - size += p->level; + union mu_opool_bucket *p; + for (p = opool->bkt_head; p; p = p->hdr.next) + size += p->hdr.level; return size; } @@ -228,14 +239,14 @@ mu_opool_copy (mu_opool_t opool, void *buf, size_t size) { char *cp = buf; size_t total = 0; - struct mu_opool_bucket *p; + union mu_opool_bucket *p; - for (p = opool->bkt_head; p && total < size; p = p->next) + for (p = opool->bkt_head; p && total < size; p = p->hdr.next) { size_t cpsize = size - total; - if (cpsize > p->level) - cpsize = p->level; - memcpy (cp, p->buf, cpsize); + if (cpsize > p->hdr.level) + cpsize = p->hdr.level; + memcpy (cp, p->hdr.buf, cpsize); cp += cpsize; total += cpsize; } @@ -249,12 +260,12 @@ mu_opool_coalesce (mu_opool_t opool, size_t *psize) if (opool->itr_count) return MU_ERR_FAILURE; - if (opool->bkt_head && opool->bkt_head->next == NULL) - size = opool->bkt_head->level; + if (opool->bkt_head && opool->bkt_head->hdr.next == NULL) + size = opool->bkt_head->hdr.level; else { - struct mu_opool_bucket *bucket; - struct mu_opool_bucket *p; + union mu_opool_bucket *bucket; + union mu_opool_bucket *p; size = mu_opool_size (opool); @@ -263,9 +274,10 @@ mu_opool_coalesce (mu_opool_t opool, size_t *psize) return ENOMEM; for (p = opool->bkt_head; p; ) { - struct mu_opool_bucket *next = p->next; - memcpy (bucket->buf + bucket->level, p->buf, p->level); - bucket->level += p->level; + union mu_opool_bucket *next = p->hdr.next; + memcpy (bucket->hdr.buf + bucket->hdr.level, p->hdr.buf, + p->hdr.level); + bucket->hdr.level += p->hdr.level; free (p); p = next; } @@ -280,8 +292,8 @@ void * mu_opool_head (mu_opool_t opool, size_t *psize) { if (psize) - *psize = opool->bkt_head ? opool->bkt_head->level : 0; - return opool->bkt_head ? opool->bkt_head->buf : NULL; + *psize = opool->bkt_head ? opool->bkt_head->hdr.level : 0; + return opool->bkt_head ? opool->bkt_head->hdr.buf : NULL; } void * @@ -290,7 +302,22 @@ mu_opool_finish (mu_opool_t opool, size_t *psize) if (mu_opool_coalesce (opool, psize)) return NULL; mu_opool_clear (opool); - return opool->bkt_fini->buf; + return opool->bkt_fini->hdr.buf; +} + +void * +mu_opool_detach (mu_opool_t opool, size_t *psize) +{ + union mu_opool_bucket *bp; + + if (mu_opool_coalesce (opool, psize)) + return NULL; + mu_opool_clear (opool); + + bp = opool->bkt_fini; + opool->bkt_fini = bp->hdr.next; + memmove (bp, bp->hdr.buf, bp->hdr.level); + return bp; } void @@ -304,24 +331,25 @@ mu_opool_free (mu_opool_t pool, void *obj) mu_opool_finish (pool, NULL); while (pool->bkt_fini) { - struct mu_opool_bucket *next = pool->bkt_fini->next; + union mu_opool_bucket *next = pool->bkt_fini->hdr.next; free (pool->bkt_fini); pool->bkt_fini = next; } } else { - struct mu_opool_bucket *bucket = pool->bkt_fini, **pprev = &pool->bkt_fini; + union mu_opool_bucket *bucket = pool->bkt_fini, + **pprev = &pool->bkt_fini; while (bucket) { - if (bucket->buf == obj) + if (bucket->hdr.buf == obj) { - *pprev = bucket->next; + *pprev = bucket->hdr.next; free (bucket); return; } - pprev = &bucket->next; - bucket = bucket->next; + pprev = &bucket->hdr.next; + bucket = bucket->hdr.next; } } } @@ -357,18 +385,18 @@ mu_opool_union (mu_opool_t *pdst, mu_opool_t *psrc) dst = *pdst; if (dst->bkt_tail) - dst->bkt_tail->next = src->bkt_head; + dst->bkt_tail->hdr.next = src->bkt_head; else dst->bkt_head = src->bkt_head; dst->bkt_tail = src->bkt_tail; if (src->bkt_fini) { - struct mu_opool_bucket *p; + union mu_opool_bucket *p; - for (p = src->bkt_fini; p->next; p = p->next) + for (p = src->bkt_fini; p->hdr.next; p = p->hdr.next) ; - p->next = dst->bkt_fini; + p->hdr.next = dst->bkt_fini; dst->bkt_fini = src->bkt_fini; } @@ -382,7 +410,7 @@ mu_opool_union (mu_opool_t *pdst, mu_opool_t *psrc) struct opool_iterator { mu_opool_t opool; - struct mu_opool_bucket *cur; + union mu_opool_bucket *cur; }; static int @@ -399,7 +427,7 @@ opitr_next (void *owner) struct opool_iterator *itr = owner; if (itr->cur) { - itr->cur = itr->cur->next; + itr->cur = itr->cur->hdr.next; return 0; } return EINVAL; @@ -412,9 +440,9 @@ opitr_getitem (void *owner, void **pret, const void **pkey) if (!itr->cur) return MU_ERR_NOENT; - *pret = itr->cur->buf; + *pret = itr->cur->hdr.buf; if (pkey) - *(size_t*) pkey = itr->cur->level; + *(size_t*) pkey = itr->cur->hdr.level; return 0; } @@ -429,7 +457,7 @@ static int opitr_delitem (void *owner, void *item) { struct opool_iterator *itr = owner; - return (itr->cur && itr->cur->buf == item) ? + return (itr->cur && itr->cur->hdr.buf == item) ? MU_ITR_DELITEM_NEXT : MU_ITR_DELITEM_NOTHING; } |