aboutsummaryrefslogtreecommitdiff
path: root/src/libventi/queue.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libventi/queue.c')
-rw-r--r--src/libventi/queue.c103
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);
+}