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

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