plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

queue.c (1570B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <venti.h>
      4 #include "queue.h"
      5 
      6 typedef struct Qel Qel;
      7 struct Qel
      8 {
      9 	Qel *next;
     10 	void *p;
     11 };
     12 
     13 struct Queue
     14 {
     15 	int ref;
     16 	int hungup;
     17 	QLock lk;
     18 	Rendez r;
     19 	Qel *head;
     20 	Qel *tail;
     21 };
     22 
     23 Queue*
     24 _vtqalloc(void)
     25 {
     26 	Queue *q;
     27 
     28 	q = vtmallocz(sizeof(Queue));
     29 	q->r.l = &q->lk;
     30 	q->ref = 1;
     31 	return q;
     32 }
     33 
     34 Queue*
     35 _vtqincref(Queue *q)
     36 {
     37 	qlock(&q->lk);
     38 	q->ref++;
     39 	qunlock(&q->lk);
     40 	return q;
     41 }
     42 
     43 void
     44 _vtqdecref(Queue *q)
     45 {
     46 	Qel *e;
     47 
     48 	qlock(&q->lk);
     49 	if(--q->ref > 0){
     50 		qunlock(&q->lk);
     51 		return;
     52 	}
     53 	assert(q->ref == 0);
     54 	qunlock(&q->lk);
     55 
     56 	/* Leaks the pointers e->p! */
     57 	while(q->head){
     58 		e = q->head;
     59 		q->head = e->next;
     60 		free(e);
     61 	}
     62 	free(q);
     63 }
     64 
     65 int
     66 _vtqsend(Queue *q, void *p)
     67 {
     68 	Qel *e;
     69 
     70 	e = vtmalloc(sizeof(Qel));
     71 	qlock(&q->lk);
     72 	if(q->hungup){
     73 		werrstr("hungup queue");
     74 		qunlock(&q->lk);
     75 		return -1;
     76 	}
     77 	e->p = p;
     78 	e->next = nil;
     79 	if(q->head == nil)
     80 		q->head = e;
     81 	else
     82 		q->tail->next = e;
     83 	q->tail = e;
     84 	rwakeup(&q->r);
     85 	qunlock(&q->lk);
     86 	return 0;
     87 }
     88 
     89 void*
     90 _vtqrecv(Queue *q)
     91 {
     92 	void *p;
     93 	Qel *e;
     94 
     95 	qlock(&q->lk);
     96 	while(q->head == nil && !q->hungup)
     97 		rsleep(&q->r);
     98 	if(q->hungup){
     99 		qunlock(&q->lk);
    100 		return nil;
    101 	}
    102 	e = q->head;
    103 	q->head = e->next;
    104 	qunlock(&q->lk);
    105 	p = e->p;
    106 	vtfree(e);
    107 	return p;
    108 }
    109 
    110 void*
    111 _vtnbqrecv(Queue *q)
    112 {
    113 	void *p;
    114 	Qel *e;
    115 
    116 	qlock(&q->lk);
    117 	if(q->head == nil){
    118 		qunlock(&q->lk);
    119 		return nil;
    120 	}
    121 	e = q->head;
    122 	q->head = e->next;
    123 	qunlock(&q->lk);
    124 	p = e->p;
    125 	vtfree(e);
    126 	return p;
    127 }
    128 
    129 void
    130 _vtqhangup(Queue *q)
    131 {
    132 	qlock(&q->lk);
    133 	q->hungup = 1;
    134 	rwakeupall(&q->r);
    135 	qunlock(&q->lk);
    136 }