From f973e29668a83bf331a28c7ab7b218754967157e Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Thu, 9 Dec 2010 15:53:53 +0100 Subject: [PATCH] src/queue.c: don't deallocate the last block when queue becomes empty. always keep one block in the queue so that in situations when the queue becomes empty frequently. performance dosent blow up by calls to malloc/free. --- src/queue.c | 47 +++++++++++++++++++++++------------------------ test/t_queue.c | 3 --- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/queue.c b/src/queue.c index 5f2d30d..c04ada2 100644 --- a/src/queue.c +++ b/src/queue.c @@ -16,12 +16,6 @@ #define BLOCK_SIZE (1<<7) -#define init(q) \ - do { \ - q->tail.n = q->head.n = NULL; \ - q->tail.i = q->head.i = 0; \ - } while(0) - /* linked list node holding a chunk of queue elements */ struct node { void *block[BLOCK_SIZE]; @@ -61,14 +55,24 @@ static void dealloc_node(struct ref *tail) { queue_t queue_init() { queue_t q = xmalloc(sizeof(struct __queue)); - - init(q); + q->tail.n = q->head.n = xmalloc(sizeof(struct node)); + q->tail.n->next = q->head.n->next = NULL; + q->tail.i = q->head.i = 0; + return q; } void queue_destroy(queue_t q) { - xfree(q); + if (q) { + struct node *n = q->tail.n; + while(n) { + struct node *next = n->next; + xfree(n); + n = next; + } + xfree(q); + } } void queue_enqueue(queue_t q, void *obj) { @@ -76,15 +80,11 @@ void queue_enqueue(queue_t q, void *obj) { if (q == NULL) return; - if (q->head.n == NULL) { - q->tail.n = q->head.n = xmalloc(sizeof(struct node)); - } else if (q->head.i + 1 >= BLOCK_SIZE) { + if (q->head.i >= BLOCK_SIZE) { alloc_node(&q->head); - } else { - q->head.i++; } - q->head.n->block[q->head.i] = obj; + q->head.n->block[q->head.i++] = obj; } void* queue_dequeue(queue_t q) { @@ -97,8 +97,7 @@ void* queue_dequeue(queue_t q) { obj = q->tail.n->block[q->tail.i++]; if (q->tail.n == q->head.n && q->tail.i > q->head.i) { - xfree(q->head.n); - init(q); + q->tail.i = q->head.i = 0; } else if (q->tail.i >= BLOCK_SIZE) { dealloc_node(&q->tail); } @@ -111,22 +110,22 @@ int queue_isempty(queue_t q) { if (q == NULL) return -1; - return q->head.n == NULL && q->head.n == q->tail.n; + return q->head.n == q->tail.n && q->head.i == q->tail.i; } size_t queue_num_items(queue_t q) { + size_t len; + struct node *n; + if (queue_isempty(q)) return 0; if (q->head.n == q->tail.n) - return (q->head.i + 1) - q->tail.i; + return q->head.i - q->tail.i; - size_t len = (BLOCK_SIZE - q->tail.i) + (q->head.i + 1); - struct node *n = q->tail.n->next; - - for(; n != q->head.n; n = n->next) + len = (BLOCK_SIZE - q->tail.i) + q->head.i; + for(n = q->tail.n->next; n != q->head.n; n = n->next) len += BLOCK_SIZE; - return len; } diff --git a/test/t_queue.c b/test/t_queue.c index 80fbe60..5e96e4b 100644 --- a/test/t_queue.c +++ b/test/t_queue.c @@ -16,9 +16,6 @@ int main() { for(i=0; i < 4; i++) { int *c = queue_dequeue(q); - if (c == NULL) - continue; - assert(c == &map[i]); }