/* Copyright (C) 2003 Russ Cox, Massachusetts Institute of Technology */ /* See COPYRIGHT */ #include #include #include typedef struct Qel Qel; struct Qel { Qel *next; void *p; }; struct Muxqueue { int hungup; QLock lk; Rendez r; Qel *head; Qel *tail; }; Muxqueue* _muxqalloc(void) { Muxqueue *q; q = mallocz(sizeof(Muxqueue), 1); if(q == nil) return nil; q->r.l = &q->lk; return q; } int _muxqsend(Muxqueue *q, void *p) { Qel *e; e = malloc(sizeof(Qel)); if(e == nil) return -1; qlock(&q->lk); if(q->hungup){ werrstr("hungup queue"); qunlock(&q->lk); free(e); 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* _muxqrecv(Muxqueue *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; free(e); return p; } void* _muxnbqrecv(Muxqueue *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; free(e); return p; } void _muxqhangup(Muxqueue *q) { qlock(&q->lk); q->hungup = 1; rwakeupall(&q->r); qunlock(&q->lk); }