1c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati/******************************************************************************
2c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati *
3c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati *  Copyright (C) 2014 Google, Inc.
4c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati *
5c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati *  Licensed under the Apache License, Version 2.0 (the "License");
6c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati *  you may not use this file except in compliance with the License.
7c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati *  You may obtain a copy of the License at:
8c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati *
9c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati *  http://www.apache.org/licenses/LICENSE-2.0
10c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati *
11c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati *  Unless required by applicable law or agreed to in writing, software
12c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati *  distributed under the License is distributed on an "AS IS" BASIS,
13c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati *  See the License for the specific language governing permissions and
15c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati *  limitations under the License.
16c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati *
17c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati ******************************************************************************/
18c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati
19c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati#include <assert.h>
20c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati#include <pthread.h>
21c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati#include <stdlib.h>
22c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
23c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati#include "fixed_queue.h"
24c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati#include "list.h"
25c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati#include "osi.h"
26c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati#include "semaphore.h"
27c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
28c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavatitypedef struct fixed_queue_t {
29c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  list_t *list;
30c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  semaphore_t *enqueue_sem;
31c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  semaphore_t *dequeue_sem;
32c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  pthread_mutex_t lock;
33c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  size_t capacity;
34c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati} fixed_queue_t;
35c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
36c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavatifixed_queue_t *fixed_queue_new(size_t capacity) {
37c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  fixed_queue_t *ret = calloc(1, sizeof(fixed_queue_t));
38c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  if (!ret)
39c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati    goto error;
40c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
41c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  ret->list = list_new(NULL);
42c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  if (!ret->list)
43c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati    goto error;
44c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
45c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  ret->enqueue_sem = semaphore_new(capacity);
46c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  if (!ret->enqueue_sem)
47c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati    goto error;
48c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
49c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  ret->dequeue_sem = semaphore_new(0);
50c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  if (!ret->dequeue_sem)
51c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati    goto error;
52c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
53c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  pthread_mutex_init(&ret->lock, NULL);
54c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  ret->capacity = capacity;
55c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
56c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  return ret;
57c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
58c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavatierror:;
59c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  if (ret) {
60c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati    list_free(ret->list);
61c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati    semaphore_free(ret->enqueue_sem);
62c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati    semaphore_free(ret->dequeue_sem);
63c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  }
64c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
65c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  free(ret);
66c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  return NULL;
67c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati}
68c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
69c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavativoid fixed_queue_free(fixed_queue_t *queue, fixed_queue_free_cb free_cb) {
70c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  if (!queue)
71c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati    return;
72c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
73c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  if (free_cb)
74c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati    for (const list_node_t *node = list_begin(queue->list); node != list_end(queue->list); node = list_next(node))
75c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati      free_cb(list_node(node));
76c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
77c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  list_free(queue->list);
78c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  semaphore_free(queue->enqueue_sem);
79c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  semaphore_free(queue->dequeue_sem);
80c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  pthread_mutex_destroy(&queue->lock);
81c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  free(queue);
82c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati}
83c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
84c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavativoid fixed_queue_enqueue(fixed_queue_t *queue, void *data) {
85c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  assert(queue != NULL);
86c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  assert(data != NULL);
87c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
88c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  semaphore_wait(queue->enqueue_sem);
89c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
90c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  pthread_mutex_lock(&queue->lock);
91c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  list_append(queue->list, data);
92c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  pthread_mutex_unlock(&queue->lock);
93c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
94c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  semaphore_post(queue->dequeue_sem);
95c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati}
96c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
97c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavativoid *fixed_queue_dequeue(fixed_queue_t *queue) {
98c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  assert(queue != NULL);
99c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
100c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  semaphore_wait(queue->dequeue_sem);
101c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
102c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  pthread_mutex_lock(&queue->lock);
103c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati  void *ret = list_front(queue->list);
104c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati  list_remove(queue->list, ret);
105c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati  pthread_mutex_unlock(&queue->lock);
106c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati
107c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati  semaphore_post(queue->enqueue_sem);
108c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati
109c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati  return ret;
110c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati}
111c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati
112c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavatibool fixed_queue_try_enqueue(fixed_queue_t *queue, void *data) {
113c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati  assert(queue != NULL);
114c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati  assert(data != NULL);
115c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati
116c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati  if (!semaphore_try_wait(queue->enqueue_sem))
117c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati    return false;
118c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati
119c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati  pthread_mutex_lock(&queue->lock);
120c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati  list_append(queue->list, data);
121c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati  pthread_mutex_unlock(&queue->lock);
122c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati
123c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati  semaphore_post(queue->dequeue_sem);
124c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati  return true;
125c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati}
126c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati
127c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavativoid *fixed_queue_try_dequeue(fixed_queue_t *queue) {
128c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati  assert(queue != NULL);
129c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati
130c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati  if (!semaphore_try_wait(queue->dequeue_sem))
131c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati    return NULL;
132c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati
133c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati  pthread_mutex_lock(&queue->lock);
134c5856ba565d4d6952f465164a98807fb274b96e6Sharvil Nanavati  void *ret = list_front(queue->list);
135c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  list_remove(queue->list, ret);
136c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  pthread_mutex_unlock(&queue->lock);
137c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
138c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  semaphore_post(queue->enqueue_sem);
139c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati
140c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati  return ret;
141c11b407e78d96e05b0991bbe6dfde0d7eb5349b5Sharvil Nanavati}
142ab606b5ecd59ab9fd8a59cf4437993a44068a6eeSharvil Nanavati
143ab606b5ecd59ab9fd8a59cf4437993a44068a6eeSharvil Nanavatiint fixed_queue_get_dequeue_fd(const fixed_queue_t *queue) {
144ab606b5ecd59ab9fd8a59cf4437993a44068a6eeSharvil Nanavati  assert(queue != NULL);
145ab606b5ecd59ab9fd8a59cf4437993a44068a6eeSharvil Nanavati  return semaphore_get_fd(queue->dequeue_sem);
146ab606b5ecd59ab9fd8a59cf4437993a44068a6eeSharvil Nanavati}
147ab606b5ecd59ab9fd8a59cf4437993a44068a6eeSharvil Nanavati
148ab606b5ecd59ab9fd8a59cf4437993a44068a6eeSharvil Nanavatiint fixed_queue_get_enqueue_fd(const fixed_queue_t *queue) {
149ab606b5ecd59ab9fd8a59cf4437993a44068a6eeSharvil Nanavati  assert(queue != NULL);
150ab606b5ecd59ab9fd8a59cf4437993a44068a6eeSharvil Nanavati  return semaphore_get_fd(queue->enqueue_sem);
151ab606b5ecd59ab9fd8a59cf4437993a44068a6eeSharvil Nanavati}
152