From 2a0c49a70b885d8392157e00ba853472c08b1dbc Mon Sep 17 00:00:00 2001
From: rswindell <>
Date: Fri, 21 May 2004 01:39:53 +0000
Subject: [PATCH] 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().

---
 src/xpdev/link_list.c | 74 ++++++++++++++++++++++++++++++++++++++++---
 src/xpdev/link_list.h | 17 ++++++++--
 2 files changed, 85 insertions(+), 6 deletions(-)

diff --git a/src/xpdev/link_list.c b/src/xpdev/link_list.c
index 7b63bc60d4..bc54490093 100644
--- a/src/xpdev/link_list.c
+++ b/src/xpdev/link_list.c
@@ -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);
 }
diff --git a/src/xpdev/link_list.h b/src/xpdev/link_list.h
index 4231537243..8af8b606c8 100644
--- a/src/xpdev/link_list.h
+++ b/src/xpdev/link_list.h
@@ -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*);
-- 
GitLab