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. LIST *list = calloc(1, sizeof(LIST));
  22. if (!list)
  23. return NULL;
  24. LNODE *node = calloc(1, sizeof(LNODE));
  25. if (!node) {
  26. free(list);
  27. return NULL;
  28. }
  29. if (pthread_mutex_init(&list->mutex,NULL) != 0) {
  30. perror("list_new: mutex_init");
  31. free(list);
  32. free(node);
  33. return NULL;
  34. }
  35. list->name = strdup(name);
  36. node->data = NULL;
  37. node->next = node;
  38. node->prev = node;
  39. list->head = node; // Point to first
  40. list->tail = node; // Set prev element
  41. Ldbg(stderr, "list_new(%s) l=%p l->head=%p l->tail=%p\n", list->name, list, list->head, list->tail);
  42. return list;
  43. }
  44. void list_free(LIST **plist, void (*free_func)(void *), void (*freep_func)(void **)) {
  45. LIST *list = *plist;
  46. if (!list)
  47. return;
  48. Ldbg(stderr, "list_free(%s)\n", list->name);
  49. LNODE *node, *tmp;
  50. list_lock(list);
  51. list_for_each(list, node, tmp) {
  52. if (free_func && node->data)
  53. free_func(node->data);
  54. if (freep_func && node->data)
  55. freep_func(&node->data);
  56. list_del_unlocked(list, &node);
  57. }
  58. FREE(list->head);
  59. list_unlock(list);
  60. pthread_mutex_destroy(&list->mutex);
  61. FREE(list->name);
  62. FREE(*plist);
  63. }
  64. void list_lock(LIST *list) {
  65. pthread_mutex_lock(&list->mutex);
  66. }
  67. void list_unlock(LIST *list) {
  68. pthread_mutex_unlock(&list->mutex);
  69. }
  70. void list_add(LIST *list, void *data) {
  71. if (!list) {
  72. Ldbg(stderr, "list_add(), list == NULL\n");
  73. return;
  74. }
  75. if (!data) {
  76. Ldbg(stderr, "list_add(%s), data == NULL\n", list->name);
  77. return;
  78. }
  79. LNODE *node = calloc(1, sizeof(LNODE));
  80. if (!node) {
  81. Ldbg(stderr, "list_add(%s), can't alloc node\n", list->name);
  82. return;
  83. }
  84. node->data = data;
  85. // if (strcmp(list->name, "clients") == 0 || strcmp(list->name, "r->clients") == 0)
  86. Ldbg(stderr, "list_add(%s), node=%p data=%p\n", list->name, node, node->data);
  87. list_lock(list);
  88. node->prev = list->tail;
  89. node->next = list->head;
  90. list->tail->next = node;
  91. list->tail = node;
  92. list->head->prev = node;
  93. list->items++;
  94. list_unlock(list);
  95. }
  96. void list_dump(LIST *list) {
  97. if (list == NULL) {
  98. fprintf(stderr, "list_dump(), list is null\n");
  99. return;
  100. }
  101. fprintf(stderr, "list_dump(%s), nodes:%d\n", list->name, list->items);
  102. LNODE *node, *tmp;
  103. int i = 0;
  104. list_for_each(list, node, tmp) {
  105. fprintf(stderr, " Node:%d Head:%p Tail:%p Node:%p NodeNext:%p NodePrev:%p Data:%p -> %s\n",
  106. i++, list->head, list->tail, node, node->next, node->prev, node->data, (char *)node->data);
  107. }
  108. }
  109. int list_del_unlocked(LIST *list, LNODE **node) {
  110. if (!list || !*node)
  111. return 0;
  112. LNODE *prev = (*node)->prev;
  113. LNODE *next = (*node)->next;
  114. next->prev = prev;
  115. prev->next = next;
  116. if (*node == list->tail)
  117. list->tail = prev;
  118. list->items--;
  119. FREE(*node);
  120. return 1;
  121. }
  122. int list_del(LIST *list, LNODE **node) {
  123. if (!list || !*node)
  124. return 0;
  125. list_lock(list);
  126. int ret = list_del_unlocked(list, node);
  127. list_unlock(list);
  128. return ret;
  129. }
  130. int list_del_entry(LIST *list, void *data) {
  131. int ret = 0;
  132. if (!list || !data)
  133. return 0;
  134. Ldbg(stderr, "list_del_entry(%s, %p)\n", list->name, data);
  135. list_lock(list);
  136. LNODE *node, *tmp;
  137. list_for_each(list, node, tmp) {
  138. if (node->data == data) {
  139. ret = list_del_unlocked(list, &node);
  140. break;
  141. }
  142. }
  143. list_unlock(list);
  144. return ret;
  145. }