Advertisement
Guest User

Untitled

a guest
Oct 16th, 2019
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.62 KB | None | 0 0
  1. #include "queue.h"
  2.  
  3. #include <pthread.h>
  4. #include <semaphore.h>
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <errno.h>
  8. #include <assert.h>
  9.  
  10. #define handle_error_en(en, msg) \
  11. do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
  12.  
  13. #define handle_error(msg) \
  14. do { perror(msg); exit(EXIT_FAILURE); } while (0)
  15.  
  16.  
  17. /*
  18. * Queue - the abstract type of a concurrent queue.
  19. * You must provide an implementation of this type
  20. * but it is hidden from the outside.
  21. */
  22. typedef struct QueueStruct {
  23. void** elements; // Array of pointers to objects in queue
  24. int size;
  25.  
  26. // Implement queue as a ring buffer:
  27. int index_last;
  28. int index_first;
  29.  
  30. // Guard the queue internals from simultaneous modification
  31. pthread_mutex_t put_guard;
  32. pthread_mutex_t get_guard;
  33.  
  34. // Also guard the queue with semaphores so it can
  35. // never be overfilled past its size or over-emptied
  36. sem_t free_slots;
  37. sem_t used_slots;
  38. } Queue;
  39.  
  40.  
  41. /**
  42. * Allocate a concurrent queue of a specific size
  43. * @param size - The size of memory to allocate to the queue
  44. * @return queue - Pointer to the allocated queue
  45. */
  46. Queue *queue_alloc(int size) {
  47. Queue* queue = malloc(sizeof(Queue));
  48.  
  49. void** elements = malloc(size * sizeof(void*));
  50. queue->elements = elements;
  51. queue->size = size;
  52. queue->index_first = 0;
  53. queue->index_last = 0;
  54.  
  55. pthread_mutex_init(&queue->put_guard, NULL);
  56. pthread_mutex_init(&queue->get_guard, NULL);
  57.  
  58. sem_init(&queue->free_slots, 0, size);
  59. sem_init(&queue->used_slots, 0, 0);
  60.  
  61. return queue;
  62. }
  63.  
  64.  
  65. /**
  66. * Free a concurrent queue and associated memory
  67. *
  68. * Don't call this function while the queue is still in use.
  69. * (Note, this is a pre-condition to the function and does not need
  70. * to be checked)
  71. *
  72. * @param queue - Pointer to the queue to free
  73. */
  74. void queue_free(Queue *queue) {
  75. // assert(0 && "not implemented yet!");
  76. }
  77.  
  78.  
  79. /**
  80. * Place an item into the concurrent queue.
  81. * If no space available then queue will block
  82. * until a space is available when it will
  83. * put the item into the queue and immediatly return
  84. *
  85. * @param queue - Pointer to the queue to add an item to
  86. * @param item - An item to add to queue. Uses void* to hold an arbitrary
  87. * type. User's responsibility to manage memory and ensure
  88. * it is correctly typed.
  89. */
  90. void queue_put(Queue *queue, void *item) {
  91. sem_wait(&queue->free_slots);
  92.  
  93. pthread_mutex_lock(&queue->put_guard);
  94. queue->elements[queue->index_last] = item;
  95. // Increment last index modulo the queue size
  96. queue->index_last = (queue->index_last + 1) % queue->size;
  97. pthread_mutex_unlock(&queue->put_guard);
  98.  
  99. sem_post(&queue->used_slots);
  100. }
  101.  
  102.  
  103. /**
  104. * Get an item from the concurrent queue
  105. *
  106. * If there is no item available then queue_get
  107. * will block until an item becomes avaible when
  108. * it will immediately return that item.
  109. *
  110. * @param queue - Pointer to queue to get item from
  111. * @return item - item retrieved from queue. void* type since it can be
  112. * arbitrary
  113. */
  114. void *queue_get(Queue *queue) {
  115. sem_wait(&queue->used_slots);
  116.  
  117.  
  118. pthread_mutex_lock(&queue->get_guard);
  119. void* item = queue->elements[queue->index_first];
  120.  
  121. // Increment first index modulo queue size
  122. queue->index_first = (queue->index_first + 1) % queue->size;
  123. pthread_mutex_unlock(&queue->get_guard);
  124.  
  125. sem_post(&queue->free_slots);
  126. return item;
  127. }
  128.  
  129. void queue_print(Queue* queue) {
  130. printf("Queue: First = %d, Last = %d\n", queue->index_first, queue->index_last);
  131. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement