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 1.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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(void) {
  17. QUEUE *q = calloc(1, sizeof(QUEUE));
  18. if (!q)
  19. return NULL;
  20. if (pthread_mutex_init(&q->mutex,NULL) != 0) {
  21. perror("queue_new: mutex_init");
  22. free(q);
  23. return NULL;
  24. }
  25. if (pthread_cond_init(&q->cond,NULL)!=0){
  26. perror("queue_new: cond_init");
  27. free(q);
  28. return NULL;
  29. }
  30. return q;
  31. }
  32. void queue_free(QUEUE **pq) {
  33. QUEUE *q = *pq;
  34. if (!q)
  35. return;
  36. while (q->items > 0) {
  37. queue_get(q);
  38. }
  39. pthread_mutex_destroy(&q->mutex);
  40. pthread_cond_destroy(&q->cond);
  41. FREE(*pq);
  42. }
  43. void queue_add(QUEUE *q, void *data) {
  44. if (!q)
  45. return;
  46. QNODE *a_msg = calloc(1, sizeof(QNODE));
  47. if (!a_msg) {
  48. perror("queue_enqueue, malloc:");
  49. return;
  50. }
  51. a_msg->data = data;
  52. a_msg->next = NULL;
  53. pthread_mutex_lock(&q->mutex);
  54. if (q->items == 0) { // special case - queue is empty
  55. q->head = a_msg;
  56. q->tail = a_msg;
  57. } else {
  58. q->tail->next = a_msg;
  59. q->tail = a_msg;
  60. }
  61. q->items++;
  62. pthread_cond_signal(&q->cond);
  63. pthread_mutex_unlock(&q->mutex);
  64. }
  65. void *queue_get(QUEUE *q) {
  66. if (!q)
  67. return NULL;
  68. pthread_mutex_lock(&q->mutex);
  69. while (q->items==0) {
  70. pthread_cond_wait(&q->cond, &q->mutex);
  71. if (q->items == 0)
  72. return NULL;
  73. }
  74. if (!q || !q->head || q->items == 0) // Can happen in free
  75. return NULL;
  76. QNODE *a_msg = q->head;
  77. q->head = a_msg->next;
  78. if (q->head == NULL) { // this was last msg
  79. q->tail = NULL;
  80. }
  81. q->items--;
  82. pthread_cond_signal(&q->cond);
  83. pthread_mutex_unlock(&q->mutex);
  84. void *data = a_msg->data;
  85. FREE(a_msg);
  86. return data;
  87. }
  88. void *queue_get_nowait(QUEUE* q) {
  89. if (!q || q->items == 0)
  90. return NULL;
  91. return queue_get(q);
  92. }
  93. void queue_wakeup(QUEUE *q) {
  94. if (q) {
  95. pthread_cond_signal(&q->cond);
  96. }
  97. }