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.

list.c 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * List manipulations
  3. * Copyright (C) 2006-2010 Unix Solutions Ltd.
  4. *
  5. * Released under MIT license.
  6. * See LICENSE-MIT.txt for license terms.
  7. */
  8. #include <string.h>
  9. #include <stdlib.h>
  10. #include <stdio.h>
  11. #include <pthread.h>
  12. #include "libfuncs.h"
  13. #include "list.h"
  14. //#define LIST_DEBUG
  15. #ifdef LIST_DEBUG
  16. #define Ldbg fprintf
  17. #else
  18. #define Ldbg(...) do { /* ... */ } while(0)
  19. #endif
  20. LIST *list_new(char *name) {
  21. pthread_mutex_t *mutex = malloc(sizeof(pthread_mutex_t));
  22. if (pthread_mutex_init(mutex,NULL) != 0) {
  23. perror("list_new: mutex_init");
  24. return NULL;
  25. }
  26. LIST *list = calloc(1, sizeof(LIST));
  27. if (!list)
  28. return NULL;
  29. list->mutex = mutex;
  30. list->name = strdup(name);
  31. LNODE *node = malloc(sizeof(LNODE));
  32. if (!node)
  33. return NULL;
  34. node->data = NULL;
  35. node->next = node;
  36. node->prev = node;
  37. list->head = node; // Point to first
  38. list->tail = node; // Set prev element
  39. Ldbg(stderr, "list_new(%s) l=%p l->head=%p l->tail=%p\n", list->name, list, list->head, list->tail);
  40. return list;
  41. }
  42. void list_free(LIST **plist, void (*free_func)(), void (*freep_func)()) {
  43. LIST *list = *plist;
  44. if (!list)
  45. return;
  46. Ldbg(stderr, "list_free(%s)\n", list->name);
  47. LNODE *node, *tmp;
  48. list_lock(list);
  49. list_for_each(list, node, tmp) {
  50. if (free_func && node->data)
  51. free_func(node->data);
  52. if (freep_func && node->data)
  53. freep_func(&node->data);
  54. list_del_unlocked(list, &node);
  55. }
  56. FREE(list->head);
  57. list_unlock(list);
  58. pthread_mutex_destroy(list->mutex);
  59. FREE(list->mutex);
  60. FREE(list->name);
  61. FREE(*plist);
  62. }
  63. void list_lock(LIST *list) {
  64. pthread_mutex_lock(list->mutex);
  65. }
  66. void list_unlock(LIST *list) {
  67. pthread_mutex_unlock(list->mutex);
  68. }
  69. void list_add(LIST *list, void *data) {
  70. if (!list) {
  71. Ldbg(stderr, "list_add(), list == NULL\n");
  72. return;
  73. }
  74. if (!data) {
  75. Ldbg(stderr, "list_add(%s), data == NULL\n", list->name);
  76. return;
  77. }
  78. LNODE *node = malloc(sizeof(LNODE));
  79. if (!node) {
  80. Ldbg(stderr, "list_add(%s), can't alloc node\n", list->name);
  81. return;
  82. }
  83. node->data = data;
  84. // if (strcmp(list->name, "clients") == 0 || strcmp(list->name, "r->clients") == 0)
  85. Ldbg(stderr, "list_add(%s), node=%p data=%p\n", list->name, node, node->data);
  86. list_lock(list);
  87. node->prev = list->tail;
  88. node->next = list->head;
  89. list->tail->next = node;
  90. list->tail = node;
  91. list->head->prev = node;
  92. list->items++;
  93. list_unlock(list);
  94. }
  95. void list_dump(LIST *list) {
  96. if (list == NULL) {
  97. fprintf(stderr, "list_dump(), list is null\n");
  98. return;
  99. }
  100. fprintf(stderr, "list_dump(%s), nodes:%d\n", list->name, list->items);
  101. LNODE *node, *tmp;
  102. int i = 0;
  103. list_for_each(list, node, tmp) {
  104. fprintf(stderr, " Node:%d Head:%p Tail:%p Node:%p NodeNext:%p NodePrev:%p Data:%p -> %s\n",
  105. i++, list->head, list->tail, node, node->next, node->prev, node->data, (char *)node->data);
  106. }
  107. }
  108. int list_del_unlocked(LIST *list, LNODE **node) {
  109. if (!list || !*node)
  110. return 0;
  111. LNODE *prev = (*node)->prev;
  112. LNODE *next = (*node)->next;
  113. next->prev = prev;
  114. prev->next = next;
  115. if (*node == list->tail)
  116. list->tail = prev;
  117. list->items--;
  118. FREE(*node);
  119. return 1;
  120. }
  121. int list_del(LIST *list, LNODE **node) {
  122. if (!list || !*node)
  123. return 0;
  124. list_lock(list);
  125. int ret = list_del_unlocked(list, node);
  126. list_unlock(list);
  127. return ret;
  128. }
  129. int list_del_entry(LIST *list, void *data) {
  130. int ret = 0;
  131. if (!list || !data)
  132. return 0;
  133. Ldbg(stderr, "list_del_entry(%s, %p)\n", list->name, data);
  134. list_lock(list);
  135. LNODE *node, *tmp;
  136. list_for_each(list, node, tmp) {
  137. if (node->data == data) {
  138. ret = list_del_unlocked(list, &node);
  139. break;
  140. }
  141. }
  142. list_unlock(list);
  143. return ret;
  144. }