diff options
Diffstat (limited to 'src/libventi/queue.c')
-rw-r--r-- | src/libventi/queue.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/libventi/queue.c b/src/libventi/queue.c new file mode 100644 index 00000000..6e9bfa8d --- /dev/null +++ b/src/libventi/queue.c @@ -0,0 +1,103 @@ +#include <u.h> +#include <libc.h> +#include <venti.h> +#include "queue.h" + +typedef struct Qel Qel; +struct Qel +{ + Qel *next; + void *p; +}; + +struct Queue +{ + int hungup; + QLock lk; + Rendez r; + Qel *head; + Qel *tail; +}; + +Queue* +_vtqalloc(void) +{ + Queue *q; + + q = vtmallocz(sizeof(Queue)); + q->r.l = &q->lk; + return q; +} + +int +_vtqsend(Queue *q, void *p) +{ + Qel *e; + + e = vtmalloc(sizeof(Qel)); + qlock(&q->lk); + if(q->hungup){ + werrstr("hungup queue"); + qunlock(&q->lk); + return -1; + } + e->p = p; + e->next = nil; + if(q->head == nil) + q->head = e; + else + q->tail->next = e; + q->tail = e; + rwakeup(&q->r); + qunlock(&q->lk); + return 0; +} + +void* +_vtqrecv(Queue *q) +{ + void *p; + Qel *e; + + qlock(&q->lk); + while(q->head == nil && !q->hungup) + rsleep(&q->r); + if(q->hungup){ + qunlock(&q->lk); + return nil; + } + e = q->head; + q->head = e->next; + qunlock(&q->lk); + p = e->p; + vtfree(e); + return p; +} + +void* +_vtnbqrecv(Queue *q) +{ + void *p; + Qel *e; + + qlock(&q->lk); + if(q->head == nil){ + qunlock(&q->lk); + return nil; + } + e = q->head; + q->head = e->next; + qunlock(&q->lk); + p = e->p; + vtfree(e); + return p; +} + +void +_vtqhangup(Queue *q) +{ + qlock(&q->lk); + q->hungup = 1; + rwakeupall(&q->r); + qunlock(&q->lk); +} |