#include #include #include #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); }