1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdbool.h>
5 #include <pthread.h>
6 #include <semaphore.h>
8 #include <list.h>
9 #include <biqueue.h>
11 struct biqueue *bq_init(struct list_head *entries)
12 {
13 struct list_head *entry, *temp;
14 int count;
15 struct biqueue *bq;
17 bq = calloc(sizeof(*bq), 1);
18 if(!bq) {
19 printf("calloc failed\n");
20 return NULL;
21 }
23 if(list_empty(entries)) {
24 printf("cannot initialise biqueue with empty list\n");
25 goto err1;
26 }
29 sem_init(&bq->src_avail, 0, 0);
30 INIT_LIST_HEAD(&bq->src);
31 INIT_LIST_HEAD(&bq->dst);
32 bq->current = NULL;
33 pthread_mutex_init(&bq->lock, NULL);
35 count = 0;
36 list_for_each_safe(entry, temp, entries) {
37 list_del(entry);
38 entry->refcount = 0;
40 if(count == 0)
41 list_add_tail(entry, &bq->dst);
42 else {
43 list_add_tail(entry, &bq->src);
44 sem_post(&bq->src_avail);
45 }
46 count++;
47 }
49 return bq;
51 err1:
52 free(bq);
53 return NULL;
54 }
56 struct list_head *bq_next_empty(struct biqueue *bq)
57 {
58 struct list_head *entry;
60 while(true) {
61 sem_wait(&bq->src_avail);
63 pthread_mutex_lock(&bq->lock);
64 if(list_empty(&bq->src)) {
65 pthread_mutex_unlock(&bq->lock);
66 continue;
67 }
69 break;
70 }
72 entry = bq->src.next;
73 list_del(entry);
74 pthread_mutex_unlock(&bq->lock);
76 return entry;
77 }
79 void bq_queue_full(struct biqueue *bq, struct list_head *entry)
80 {
81 pthread_mutex_lock(&bq->lock);
82 list_add_tail(entry, &bq->dst);
83 pthread_mutex_unlock(&bq->lock);
84 }
86 struct list_head *bq_next_full(struct biqueue *bq)
87 {
88 struct list_head *entry;
90 pthread_mutex_lock(&bq->lock);
91 if(list_empty(&bq->dst)) {
92 entry = bq->current;
93 goto out;
94 }
96 entry = bq->dst.next;
97 list_del(entry);
98 bq->current = entry;
100 out:
101 entry->refcount++;
102 pthread_mutex_unlock(&bq->lock);
103 return entry;
104 }
106 void bq_queue_empty(struct biqueue *bq, struct list_head *entry)
107 {
108 entry->refcount--;
109 if(!entry->refcount) {
110 pthread_mutex_lock(&bq->lock);
111 list_add_tail(entry, &bq->src);
112 sem_post(&bq->src_avail);
113 pthread_mutex_unlock(&bq->lock);
114 }
115 }