123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- /*
- * List manipulations
- * Copyright (C) 2006-2010 Unix Solutions Ltd.
- *
- * Released under MIT license.
- * See LICENSE-MIT.txt for license terms.
- */
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <pthread.h>
-
- #include "libfuncs.h"
- #include "list.h"
-
- //#define LIST_DEBUG
-
- #ifdef LIST_DEBUG
- #define Ldbg fprintf
- #else
- #define Ldbg(...) do { /* ... */ } while(0)
- #endif
-
- LIST *list_new(char *name) {
- LIST *list = calloc(1, sizeof(LIST));
- if (!list)
- return NULL;
- LNODE *node = calloc(1, sizeof(LNODE));
- if (!node) {
- free(list);
- return NULL;
- }
- if (pthread_mutex_init(&list->mutex,NULL) != 0) {
- perror("list_new: mutex_init");
- free(list);
- free(node);
- return NULL;
- }
- list->name = strdup(name);
-
- node->data = NULL;
- node->next = node;
- node->prev = node;
-
- list->head = node; // Point to first
- list->tail = node; // Set prev element
-
- Ldbg(stderr, "list_new(%s) l=%p l->head=%p l->tail=%p\n", list->name, list, list->head, list->tail);
- return list;
- }
-
- void list_free(LIST **plist, void (*free_func)(void *), void (*freep_func)(void **)) {
- LIST *list = *plist;
- if (!list)
- return;
- Ldbg(stderr, "list_free(%s)\n", list->name);
- LNODE *node, *tmp;
- list_lock(list);
- list_for_each(list, node, tmp) {
- if (free_func && node->data)
- free_func(node->data);
- if (freep_func && node->data)
- freep_func(&node->data);
- list_del_unlocked(list, &node);
- }
- FREE(list->head);
- list_unlock(list);
- pthread_mutex_destroy(&list->mutex);
- FREE(list->name);
- FREE(*plist);
- }
-
- void list_lock(LIST *list) {
- pthread_mutex_lock(&list->mutex);
- }
-
- void list_unlock(LIST *list) {
- pthread_mutex_unlock(&list->mutex);
- }
-
- void list_add(LIST *list, void *data) {
- if (!list) {
- Ldbg(stderr, "list_add(), list == NULL\n");
- return;
- }
-
- if (!data) {
- Ldbg(stderr, "list_add(%s), data == NULL\n", list->name);
- return;
- }
-
- LNODE *node = calloc(1, sizeof(LNODE));
- if (!node) {
- Ldbg(stderr, "list_add(%s), can't alloc node\n", list->name);
- return;
- }
-
- node->data = data;
-
- // if (strcmp(list->name, "clients") == 0 || strcmp(list->name, "r->clients") == 0)
- Ldbg(stderr, "list_add(%s), node=%p data=%p\n", list->name, node, node->data);
-
- list_lock(list);
-
- node->prev = list->tail;
- node->next = list->head;
-
- list->tail->next = node;
- list->tail = node;
- list->head->prev = node;
-
- list->items++;
- list_unlock(list);
- }
-
- void list_dump(LIST *list) {
- if (list == NULL) {
- fprintf(stderr, "list_dump(), list is null\n");
- return;
- }
- fprintf(stderr, "list_dump(%s), nodes:%d\n", list->name, list->items);
- LNODE *node, *tmp;
- int i = 0;
- list_for_each(list, node, tmp) {
- fprintf(stderr, " Node:%d Head:%p Tail:%p Node:%p NodeNext:%p NodePrev:%p Data:%p -> %s\n",
- i++, list->head, list->tail, node, node->next, node->prev, node->data, (char *)node->data);
- }
- }
-
- int list_del_unlocked(LIST *list, LNODE **node) {
- if (!list || !*node)
- return 0;
-
- LNODE *prev = (*node)->prev;
- LNODE *next = (*node)->next;
-
- next->prev = prev;
- prev->next = next;
- if (*node == list->tail)
- list->tail = prev;
-
- list->items--;
-
- FREE(*node);
- return 1;
- }
-
-
- int list_del(LIST *list, LNODE **node) {
- if (!list || !*node)
- return 0;
- list_lock(list);
- int ret = list_del_unlocked(list, node);
- list_unlock(list);
- return ret;
- }
-
- int list_del_entry(LIST *list, void *data) {
- int ret = 0;
- if (!list || !data)
- return 0;
- Ldbg(stderr, "list_del_entry(%s, %p)\n", list->name, data);
- list_lock(list);
- LNODE *node, *tmp;
- list_for_each(list, node, tmp) {
- if (node->data == data) {
- ret = list_del_unlocked(list, &node);
- break;
- }
- }
- list_unlock(list);
- return ret;
- }
|