libfuncs is collection of code (list, queue, circular buffer, io, logging, etc.). https://georgi.unixsol.org/programs/libfuncs/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

queue.c 2.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. * Queue handling
  3. * Copyright (C) 2006 Unix Solutions Ltd.
  4. *
  5. * Released under MIT license.
  6. * See LICENSE-MIT.txt for license terms.
  7. */
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <assert.h>
  11. #include <errno.h>
  12. #include <err.h>
  13. #include <pthread.h>
  14. #include "libfuncs.h"
  15. #include "queue.h"
  16. QUEUE *queue_new() {
  17. pthread_mutex_t *mutex = malloc(sizeof(pthread_mutex_t));
  18. if (pthread_mutex_init(mutex,NULL) != 0) {
  19. perror("queue_new: mutex_init");
  20. return NULL;
  21. }
  22. pthread_cond_t *cond = malloc(sizeof(pthread_cond_t));
  23. if (pthread_cond_init(cond,NULL)!=0){
  24. perror("queue_new: cond_init");
  25. return NULL;
  26. }
  27. QUEUE *q = calloc(1, sizeof(QUEUE));
  28. if (!q)
  29. return NULL;
  30. // initialize queue
  31. q->mutex = mutex;
  32. q->cond = cond;
  33. return q;
  34. }
  35. void queue_free(QUEUE **pq) {
  36. QUEUE *q = *pq;
  37. void *data;
  38. if (!q)
  39. return;
  40. while (q->items > 0) {
  41. data = queue_get(q);
  42. }
  43. pthread_mutex_destroy(q->mutex);
  44. FREE(q->mutex);
  45. pthread_cond_destroy(q->cond);
  46. FREE(q->cond);
  47. FREE(*pq);
  48. }
  49. void queue_add(QUEUE *q, void *data) {
  50. if (!q)
  51. return;
  52. QNODE *a_msg = malloc(sizeof(QNODE));
  53. if (!a_msg) {
  54. perror("queue_enqueue, malloc:");
  55. return;
  56. }
  57. a_msg->data = data;
  58. a_msg->next = NULL;
  59. pthread_mutex_lock(q->mutex);
  60. if (q->items == 0) { // special case - queue is empty
  61. q->head = a_msg;
  62. q->tail = a_msg;
  63. } else {
  64. q->tail->next = a_msg;
  65. q->tail = a_msg;
  66. }
  67. q->items++;
  68. pthread_cond_signal(q->cond);
  69. pthread_mutex_unlock(q->mutex);
  70. }
  71. void *queue_get(QUEUE *q) {
  72. if (!q)
  73. return NULL;
  74. pthread_mutex_lock(q->mutex);
  75. while (q->items==0) {
  76. pthread_cond_wait(q->cond, q->mutex);
  77. if (q->items == 0)
  78. return NULL;
  79. }
  80. if (!q || !q->head || q->items == 0) // Can happen in free
  81. return NULL;
  82. QNODE *a_msg = q->head;
  83. q->head = a_msg->next;
  84. if (q->head == NULL) { // this was last msg
  85. q->tail = NULL;
  86. }
  87. q->items--;
  88. pthread_cond_signal(q->cond);
  89. pthread_mutex_unlock(q->mutex);
  90. void *data = a_msg->data;
  91. FREE(a_msg);
  92. return data;
  93. }
  94. void *queue_get_nowait(QUEUE* q) {
  95. if (!q || q->items == 0)
  96. return NULL;
  97. return queue_get(q);
  98. }
  99. void queue_wakeup(QUEUE *q) {
  100. if (q) {
  101. pthread_cond_signal(q->cond);
  102. }
  103. }