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.
This commit is contained in:
parent
3110bbf761
commit
f973e29668
2 changed files with 23 additions and 27 deletions
47
src/queue.c
47
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
}
|
||||
|
||||
|
|
|
|||
Reference in a new issue