nmdb: Add LevelDB support
[nmdb.git] / nmdb / queue.c
blob0629f8249529677d9578883d4ba257f0f5c93168
2 #include <stdlib.h> /* for malloc() */
3 #include <pthread.h> /* for mutexes */
5 #include "queue.h"
8 struct queue *queue_create(void)
10 struct queue *q;
11 pthread_mutexattr_t attr;
13 q = malloc(sizeof(struct queue));
14 if (q == NULL)
15 return NULL;
17 q->size = 0;
18 q->top = NULL;
19 q->bottom = NULL;
21 pthread_mutexattr_init(&attr);
22 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
23 pthread_mutex_init(&(q->lock), &attr);
24 pthread_mutexattr_destroy(&attr);
26 pthread_cond_init(&(q->cond), NULL);
28 return q;
31 void queue_free(struct queue *q)
33 struct queue_entry *e;
35 /* We know when we're called there is no other possible queue user;
36 * however, we don't have any sane way to tell sparse about this, so
37 * fake the acquisition of the lock to comply with the operations
38 * performed inside. Obviously, it would be completely safe to do the
39 * queue_lock()/unlock(), but it'd be misleading to the reader */
40 __acquire(q->lock);
41 e = queue_get(q);
42 while (e != NULL) {
43 queue_entry_free(e);
44 e = queue_get(q);
46 __release(q->lock);
48 pthread_mutex_destroy(&(q->lock));
50 free(q);
51 return;
55 void queue_lock(struct queue *q)
57 pthread_mutex_lock(&(q->lock));
60 void queue_unlock(struct queue *q)
62 pthread_mutex_unlock(&(q->lock));
65 void queue_signal(struct queue *q)
67 pthread_cond_signal(&(q->cond));
70 int queue_timedwait(struct queue *q, struct timespec *ts)
72 return pthread_cond_timedwait(&(q->cond), &(q->lock), ts);
76 struct queue_entry *queue_entry_create(void)
78 struct queue_entry *e;
80 e = malloc(sizeof(struct queue_entry));
81 if (e == NULL)
82 return NULL;
84 e->operation = 0;
85 e->key = NULL;
86 e->val = NULL;
87 e->newval = NULL;
88 e->ksize = 0;
89 e->vsize = 0;
90 e->nvsize = 0;
91 e->prev = NULL;
93 return e;
96 void queue_entry_free(struct queue_entry *e) {
97 if (e->req) {
98 free(e->req->clisa);
99 free(e->req);
101 if (e->key)
102 free(e->key);
103 if (e->val)
104 free(e->val);
105 if (e->newval)
106 free(e->newval);
107 free(e);
108 return;
112 void queue_put(struct queue *q, struct queue_entry *e)
114 if (q->top == NULL) {
115 q->top = q->bottom = e;
116 } else {
117 q->top->prev = e;
118 q->top = e;
120 q->size += 1;
121 return;
124 struct queue_entry *queue_get(struct queue *q)
126 struct queue_entry *e, *t;
128 if (q->bottom == NULL)
129 return NULL;
131 e = q->bottom;
132 t = q->bottom->prev;
133 q->bottom = t;
134 if (t == NULL) {
135 /* it's empty now */
136 q->top = NULL;
138 q->size -= 1;
139 return e;
142 int queue_isempty(struct queue *q)
144 return (q->size == 0);