summaryrefslogtreecommitdiff
path: root/sys/src/libventi/queue.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/libventi/queue.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/libventi/queue.c')
-rwxr-xr-xsys/src/libventi/queue.c136
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);
+}