diff --git a/src/fs/queue.c b/src/fs/queue.c new file mode 100644 index 0000000..7ba3dad --- /dev/null +++ b/src/fs/queue.c @@ -0,0 +1,153 @@ +/* src/fs/notify_queue.c + * + * Copyright (C) 2010 Henrik Hautakoski + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include "queue.h" + +#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]; + struct node *next; +}; + +struct ref { + uint16_t i; + struct node *n; +}; + +struct __queue { + struct ref tail; + struct ref head; +}; + +static void alloc_node(struct ref *head) { + + struct node *n = malloc(sizeof(struct node)); + assert(n != NULL); + + n->next = NULL; + head->n = head->n->next = n; + head->i = 0; +} + +static void dealloc_node(struct ref *tail) { + + struct node *next = tail->n->next; + assert(next != NULL); + + free(tail->n); + + tail->n = next; + tail->i = 0; +} + +queue_t* init_queue() { + + queue_t *q = malloc(sizeof(queue_t)); + + init(q); + + return q; +} + +void queue_clear(queue_t *q) { + + struct node *t, *n; + + if (q == NULL) + return; + + n = q->tail.n; + + while(n) { + t = n->next; + free(n); + n = t; + } + + init(q); +} + +void queue_destroy(queue_t *q) { + + queue_clear(q); + free(q); +} + +void queue_enqueue(queue_t *q, void *obj) { + + if (q->head.n == NULL) { + q->tail.n = q->head.n = malloc(sizeof(struct node)); + assert(q->tail.n != NULL); + } else if (q->head.i + 1 >= BLOCK_SIZE) { + alloc_node(&q->head); + } else { + q->head.i++; + } + + q->head.n->block[q->head.i] = obj; +} + +void* queue_dequeue(queue_t *q) { + + void *obj; + + if (queue_isempty(q)) + return NULL; + + obj = q->tail.n->block[q->tail.i++]; + + if (q->tail.n == q->head.n && q->tail.i > q->head.i) { + free(q->head.n); + init(q); + } else if (q->tail.i >= BLOCK_SIZE) { + dealloc_node(&q->tail); + } + + return obj; +} + +int queue_isempty(queue_t *q) { + + if (q == NULL) + return -1; + + return q->head.n == NULL && q->head.n == q->tail.n; +} + +size_t queue_num_items(queue_t *q) { + + if (queue_isempty(q)) + return 0; + if (q->head.n == q->tail.n) + return (q->head.i + 1) - 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; + + return len; +} + diff --git a/src/fs/queue.h b/src/fs/queue.h new file mode 100644 index 0000000..fda3241 --- /dev/null +++ b/src/fs/queue.h @@ -0,0 +1,35 @@ +/* src/fs/notify_queue.c + * + * Copyright (C) 2010 Henrik Hautakoski + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __FS_QUEUE_H +#define __FS_QUEUE_H + +#include + +typedef struct __queue queue_t; + +queue_t* init_queue(void); + +void queue_enqueue(queue_t *q, void *obj); + +void* queue_dequeue(queue_t *q); + +int queue_isempty(queue_t *q); + +size_t queue_num_items(queue_t *q); + +void queue_clear(queue_t *q); + +void queue_destroy(queue_t *q); + +#endif /* __FS_QUEUE_H */ diff --git a/test/Makefile b/test/Makefile index 061d292..d7ac891 100644 --- a/test/Makefile +++ b/test/Makefile @@ -31,7 +31,7 @@ inotify : ../src/fs/notify_event.c \ ../src/fs/inotify.c \ t_inotify.c -o test_inotify - + tree : $(CC) $(CFLAGS) $(DEFS) ../src/common/path.c ../src/fs/tree.c t_tree.c -o test_tree @@ -41,3 +41,6 @@ indexer : mysql : $(CC) -D DB_DEBUG $(CFLAGS) ../src/mysql_db.c -L/usr/lib64/mysql \ -lmysqlclient -lz -lcrypt -lnsl -lm -L/usr/lib64 -lssl -lcrypto t_mysql.c -o test_mysql + +queue : + $(CC) $(CFLAGS) ../src/fs/queue.c t_queue.c -o test_queue diff --git a/test/t_queue.c b/test/t_queue.c new file mode 100644 index 0000000..a82536b --- /dev/null +++ b/test/t_queue.c @@ -0,0 +1,31 @@ + +#include +#include +#include "../src/fs/queue.h" + +int main() { + + int i, map[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + queue_t *q = init_queue(); + + for(i=0; i < 10; i++) + queue_enqueue(q, &map[i]); + + assert(queue_num_items(q) == 10); + + for(i=0; i < 4; i++) { + int *c = queue_dequeue(q); + + if (c == NULL) + continue; + + assert(c == &map[i]); + } + + for(i=4; i < 10; i++) + queue_enqueue(q, &map[i]); + + queue_destroy(q); + + return 0; +}