1 /*
2  * Copyright © 2016 Mozilla Foundation
3  *
4  * This program is made available under an ISC-style license.  See the
5  * accompanying file LICENSE for details.
6  */
7 
8 #ifndef CUBEB_ARRAY_QUEUE_H
9 #define CUBEB_ARRAY_QUEUE_H
10 
11 #include <assert.h>
12 #include <pthread.h>
13 #include <unistd.h>
14 
15 #if defined(__cplusplus)
16 extern "C" {
17 #endif
18 
19 typedef struct
20 {
21   void ** buf;
22   size_t num;
23   size_t writePos;
24   size_t readPos;
25   pthread_mutex_t mutex;
26 } array_queue;
27 
array_queue_create(size_t num)28 array_queue * array_queue_create(size_t num)
29 {
30   assert(num != 0);
31   array_queue * new_queue = (array_queue*)calloc(1, sizeof(array_queue));
32   new_queue->buf = (void **)calloc(1, sizeof(void *) * num);
33   new_queue->readPos = 0;
34   new_queue->writePos = 0;
35   new_queue->num = num;
36 
37   pthread_mutex_init(&new_queue->mutex, NULL);
38 
39   return new_queue;
40 }
41 
array_queue_destroy(array_queue * aq)42 void array_queue_destroy(array_queue * aq)
43 {
44   assert(aq);
45 
46   free(aq->buf);
47   pthread_mutex_destroy(&aq->mutex);
48   free(aq);
49 }
50 
array_queue_push(array_queue * aq,void * item)51 int array_queue_push(array_queue * aq, void * item)
52 {
53   assert(item);
54 
55   pthread_mutex_lock(&aq->mutex);
56   int ret = -1;
57   if(aq->buf[aq->writePos % aq->num] == NULL)
58   {
59     aq->buf[aq->writePos % aq->num] = item;
60     aq->writePos = (aq->writePos + 1) % aq->num;
61     ret = 0;
62   }
63   // else queue is full
64   pthread_mutex_unlock(&aq->mutex);
65   return ret;
66 }
67 
array_queue_pop(array_queue * aq)68 void* array_queue_pop(array_queue * aq)
69 {
70   pthread_mutex_lock(&aq->mutex);
71   void * value = aq->buf[aq->readPos % aq->num];
72   if(value)
73   {
74     aq->buf[aq->readPos % aq->num] = NULL;
75     aq->readPos = (aq->readPos + 1) % aq->num;
76   }
77   pthread_mutex_unlock(&aq->mutex);
78   return value;
79 }
80 
array_queue_get_size(array_queue * aq)81 size_t array_queue_get_size(array_queue * aq)
82 {
83   pthread_mutex_lock(&aq->mutex);
84   ssize_t r = aq->writePos - aq->readPos;
85   if (r < 0) {
86     r = aq->num + r;
87     assert(r >= 0);
88   }
89   pthread_mutex_unlock(&aq->mutex);
90   return (size_t)r;
91 }
92 
93 #if defined(__cplusplus)
94 }
95 #endif
96 
97 #endif //CUBE_ARRAY_QUEUE_H
98