Commit 2a0c49a7 authored by rswindell's avatar rswindell
Browse files

If LINK_LIST_THREADSAFE is defined, then listInit() supports a LINK_LIST_MUTEX

flag bit to specify that the linked-list is to be auto-mutex-protected for
safe access from multiple simultaneous threads.
List nodes now have a pointer back to the list itself - used in listExtract().
parent fc6268cf
......@@ -39,10 +39,21 @@
#include <string.h> /* memset */
#include "link_list.h"
link_list_t* listInit(link_list_t* list)
#if defined(LINK_LIST_THREADSAFE)
#define MUTEX_INIT(list) if(list->flags&LINK_LIST_MUTEX) pthread_mutex_init(&list->mutex,NULL);
#define MUTEX_DESTROY(list) if(list->flags&LINK_LIST_MUTEX) pthread_mutex_destroy(&list->mutex);
#define MUTEX_LOCK(list) if(list->flags&LINK_LIST_MUTEX) pthread_mutex_lock(&list->mutex);
#define MUTEX_UNLOCK(list) if(list->flags&LINK_LIST_MUTEX) pthread_mutex_unlock(&list->mutex);
#else
#define MUTEX_INIT(list)
#define MUTEX_DESTROY(list)
#define MUTEX_LOCK(list)
#define MUTEX_UNLOCK(list)
#endif
link_list_t* listInit(link_list_t* list, long flags)
{
unsigned long flags=0;
if(flags&LINK_LIST_MALLOC || list==NULL) {
if((list=(link_list_t*)malloc(sizeof(link_list_t)))==NULL)
return(NULL);
......@@ -53,6 +64,8 @@ link_list_t* listInit(link_list_t* list)
list->flags = flags;
MUTEX_INIT(list);
return(list);
}
......@@ -91,12 +104,24 @@ link_list_t* listFree(link_list_t* list)
listFreeNodes(list);
MUTEX_DESTROY(list);
if(list->flags&LINK_LIST_MALLOC)
free(list), list=NULL;
return(list);
}
void listLock(link_list_t* list)
{
MUTEX_LOCK(list);
}
void listUnlock(link_list_t* list)
{
MUTEX_UNLOCK(list);
}
long listCountNodes(const link_list_t* list)
{
long count=0;
......@@ -108,9 +133,13 @@ long listCountNodes(const link_list_t* list)
if(list->count)
return(list->count);
MUTEX_LOCK(list);
for(node=list->first; node!=NULL; node=node->next)
count++;
MUTEX_UNLOCK(list);
return(count);
}
......@@ -121,10 +150,14 @@ list_node_t* listFindNode(const link_list_t* list, void* data, size_t length)
if(list==NULL)
return(NULL);
MUTEX_LOCK(list);
for(node=list->first; node!=NULL; node=node->next)
if(node->data!=NULL && memcmp(node->data,data,length)==0)
break;
MUTEX_UNLOCK(list);
return(node);
}
......@@ -139,11 +172,15 @@ str_list_t listStringList(const link_list_t* list)
if((str_list=strListInit())==NULL)
return(NULL);
MUTEX_LOCK(list);
for(node=list->first; node!=NULL; node=node->next) {
if(node->data!=NULL)
strListAdd(&str_list, node->data);
}
MUTEX_UNLOCK(list);
return(str_list);
}
......@@ -158,6 +195,8 @@ str_list_t listSubStringList(const list_node_t* node, long max)
if((str_list=strListInit())==NULL)
return(NULL);
MUTEX_LOCK(list);
for(count=0; count<max && node!=NULL; node=node->next) {
if(node->data!=NULL) {
strListAdd(&str_list, node->data);
......@@ -165,6 +204,8 @@ str_list_t listSubStringList(const list_node_t* node, long max)
}
}
MUTEX_UNLOCK(list);
return(str_list);
}
......@@ -187,9 +228,13 @@ list_node_t* listLastNode(const link_list_t* list)
if(list->last!=NULL)
return(list->last);
MUTEX_LOCK(list);
for(node=list->first; node!=NULL; node=node->next)
last=node;
MUTEX_UNLOCK(list);
return(last);
}
......@@ -201,10 +246,14 @@ long listNodeIndex(const link_list_t* list, list_node_t* find_node)
if(list==NULL)
return(-1);
MUTEX_LOCK(list);
for(node=list->first; node!=NULL; node=node->next)
if(node==find_node)
break;
MUTEX_UNLOCK(list);
if(node==NULL)
return(-1);
......@@ -219,9 +268,13 @@ list_node_t* listNodeAt(const link_list_t* list, long index)
if(list==NULL || index<0)
return(NULL);
MUTEX_LOCK(list);
for(node=list->first; node!=NULL && i<index; node=node->next)
i++;
MUTEX_UNLOCK(list);
return(node);
}
......@@ -254,6 +307,9 @@ static list_node_t* list_add_node(link_list_t* list, list_node_t* node, list_nod
if(list==NULL)
return(NULL);
MUTEX_LOCK(list);
node->list = list;
node->prev = after;
if(after==list->last) /* append to list */
......@@ -273,6 +329,8 @@ static list_node_t* list_add_node(link_list_t* list, list_node_t* node, list_nod
list->count++;
MUTEX_UNLOCK(list);
return(node);
}
......@@ -403,7 +461,7 @@ link_list_t* listExtract(link_list_t* dest_list, const list_node_t* node, long m
if(node==NULL)
return(NULL);
if((list=listInit(dest_list))==NULL)
if((list=listInit(dest_list, node->list->flags))==NULL)
return(NULL);
for(count=0; count<max && node!=NULL; node=node->next) {
......@@ -426,6 +484,8 @@ void* listRemoveNode(link_list_t* list, list_node_t* node)
if(node==NULL)
return(NULL);
MUTEX_LOCK(list);
if(node->prev!=NULL)
node->prev->next = node->next;
if(node->next!=NULL)
......@@ -445,6 +505,8 @@ void* listRemoveNode(link_list_t* list, list_node_t* node)
if(list->count)
list->count--;
MUTEX_UNLOCK(list);
return(data);
}
......@@ -455,11 +517,15 @@ long listRemoveNodes(link_list_t* list, list_node_t* node, long max)
if(list==NULL)
return(-1);
MUTEX_LOCK(list);
if(node==NULL)
node=list->first;
for(count=0; node!=NULL && count<max; node=node->next, count++)
listRemoveNode(list, node);
MUTEX_UNLOCK(list);
return(count);
}
......
......@@ -41,6 +41,10 @@
#include <stddef.h> /* size_t */
#include "str_list.h" /* string list functions and types */
#if defined(LINK_LIST_THREADSAFE)
#include "threadwrap.h"
#endif
#if defined(__cplusplus)
extern "C" {
#endif
......@@ -48,27 +52,36 @@ extern "C" {
/* Valid link_list_t.flags bits */
#define LINK_LIST_MALLOC (1<<0) /* List/node allocated with malloc() */
#define LINK_LIST_ALWAYS_FREE (1<<1) /* Always free node data when removing */
#define LINK_LIST_MUTEX (1<<2) /* Mutex protected linked-list */
typedef struct list_node {
void* data; /* pointer to some kind of data */
struct list_node* next; /* next node in list (or NULL) */
struct list_node* prev; /* previous node in list (or NULL) */
struct link_list* list;
unsigned long flags; /* private use flags */
} list_node_t;
typedef struct {
typedef struct link_list {
list_node_t* first; /* first node in list (or NULL) */
list_node_t* last; /* last node in list (or NULL) */
unsigned long flags; /* private use flags */
long count; /* number of nodes in list */
#if defined(LINK_LIST_THREADSAFE)
pthread_mutex_t mutex;
#endif
} link_list_t;
/* Initialization, Allocation, and Freeing of Lists and Nodes */
link_list_t* listInit(link_list_t* /* NULL to auto-allocate */);
link_list_t* listInit(link_list_t* /* NULL to auto-allocate */, long flags);
link_list_t* listFree(link_list_t*);
void listFreeNodes(link_list_t*);
void listFreeNodeData(list_node_t* node);
/* Lock/unlock mutex-protoected linked lists */
void listLock(link_list_t*);
void listUnlock(link_list_t*);
/* Return count or index of nodes, or -1 on error */
long listCountNodes(const link_list_t*);
long listNodeIndex(const link_list_t*, list_node_t*);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment