From: Jim Jagielski Date: Wed, 19 Jun 2013 01:00:46 +0000 (+0000) Subject: use a simple allocation list to enable re-use of X-Git-Tag: 2.5.0-alpha~5322 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=80f0769562d966e119aa10644c76129ea776d380;p=apache use a simple allocation list to enable re-use of "freed" chunks. If not using pools, we assume malloc/free is sane. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1494407 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/server/skiplist.c b/server/skiplist.c index 88d3df8b29..540af87ff1 100644 --- a/server/skiplist.c +++ b/server/skiplist.c @@ -37,6 +37,7 @@ struct ap_skiplist { ap_skiplistnode *topend; ap_skiplistnode *bottomend; ap_skiplist *index; + apr_array_header_t *memlist; apr_pool_t *pool; }; @@ -51,7 +52,6 @@ struct ap_skiplistnode { ap_skiplist *sl; }; - #ifndef MIN #define MIN(a,b) ((a> (ph - 1)); } +typedef struct { + size_t size; + apr_array_header_t *list; +} memlist_t; + +typedef struct { + void *ptr; + char inuse; +} chunk_t; + AP_DECLARE(void *) ap_skiplist_alloc(ap_skiplist *sl, size_t size) { if (sl->pool) { - return apr_pcalloc(sl->pool, size); + void *ptr; + int found_size = 0; + chunk_t *newchunk; + memlist_t *memlist = (memlist_t *)sl->memlist->elts; + for (int i = 0; i < sl->memlist->nelts; i++) { + if (memlist->size == size) { + found_size = 1; + chunk_t *chunk = (chunk_t *)memlist->list->elts; + for (int j = 0; j < memlist->list->nelts; j++) { + if (!chunk->inuse) { + chunk->inuse = 1; + return chunk->ptr; + } + chunk++; + } + break; /* no free of this size; punt */ + } + memlist++; + } + /* no free chunks */ + ptr = apr_pcalloc(sl->pool, size); + if (!ptr) { + return ptr; + } + /* + * is this a new sized chunk? If so, we need to create a new + * array of them. Otherwise, re-use what we already have. + */ + if (!found_size) { + memlist = apr_array_push(sl->memlist); + memlist->size = size; + memlist->list = apr_array_make(sl->pool, 20, sizeof(chunk_t)); + } + newchunk = apr_array_push(memlist->list); + newchunk->ptr = ptr; + newchunk->inuse = 1; + return ptr; } else { return ap_calloc(1, size); @@ -83,6 +129,20 @@ AP_DECLARE(void) ap_skiplist_free(ap_skiplist *sl, void *mem) if (!sl->pool) { free(mem); } + else { + memlist_t *memlist = (memlist_t *)sl->memlist->elts; + for (int i = 0; i < sl->memlist->nelts; i++) { + chunk_t *chunk = (chunk_t *)memlist->list->elts; + for (int j = 0; j < memlist->list->nelts; j++) { + if (chunk->ptr == mem) { + chunk->inuse = 0; + return; + } + chunk++; + } + memlist++; + } + } } static apr_status_t skiplisti_init(ap_skiplist **s, apr_pool_t *p) @@ -90,6 +150,7 @@ static apr_status_t skiplisti_init(ap_skiplist **s, apr_pool_t *p) ap_skiplist *sl; if (p) { sl = apr_pcalloc(p, sizeof(ap_skiplist)); + sl->memlist = apr_array_make(p, 20, sizeof(memlist_t)); } else { sl = ap_calloc(1, sizeof(ap_skiplist));