diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/libventi/queue.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/libventi/queue.c')
-rwxr-xr-x | sys/src/libventi/queue.c | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/sys/src/libventi/queue.c b/sys/src/libventi/queue.c new file mode 100755 index 000000000..bba630324 --- /dev/null +++ b/sys/src/libventi/queue.c @@ -0,0 +1,136 @@ +#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 ref; + int hungup; + QLock lk; + Rendez r; + Qel *head; + Qel *tail; +}; + +Queue* +_vtqalloc(void) +{ + Queue *q; + + q = vtmallocz(sizeof(Queue)); + q->r.l = &q->lk; + q->ref = 1; + return q; +} + +Queue* +_vtqincref(Queue *q) +{ + qlock(&q->lk); + q->ref++; + qunlock(&q->lk); + return q; +} + +void +_vtqdecref(Queue *q) +{ + Qel *e; + + qlock(&q->lk); + if(--q->ref > 0){ + qunlock(&q->lk); + return; + } + assert(q->ref == 0); + qunlock(&q->lk); + + /* Leaks the pointers e->p! */ + while(q->head){ + e = q->head; + q->head = e->next; + free(e); + } + free(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); +} |