From 4521d7ea9a157c1e3fef0248610161d1957fce40 Mon Sep 17 00:00:00 2001
From: rswindell <>
Date: Fri, 21 May 2004 02:31:33 +0000
Subject: [PATCH] Added support for primitive linked-list node locking. No
 longer support NULL data values.

---
 src/xpdev/link_list.c | 70 ++++++++++++++++++++++++++++++++-----------
 src/xpdev/link_list.h | 16 ++++++----
 2 files changed, 63 insertions(+), 23 deletions(-)

diff --git a/src/xpdev/link_list.c b/src/xpdev/link_list.c
index bc54490093..80dbbda7a6 100644
--- a/src/xpdev/link_list.c
+++ b/src/xpdev/link_list.c
@@ -69,55 +69,66 @@ link_list_t* listInit(link_list_t* list, long flags)
 	return(list);
 }
 
-void listFreeNodeData(list_node_t* node)
+BOOL listFreeNodeData(list_node_t* node)
 {
-	if(node!=NULL && node->data!=NULL) {
+	if(node!=NULL && node->data!=NULL && !(node->flags&LINK_LIST_NODE_LOCKED)) {
 		free(node->data);
 		node->data = NULL;
+		return(TRUE);
 	}
+	return(FALSE);
 }
 
-void listFreeNodes(link_list_t* list)
+long listFreeNodes(link_list_t* list)
 {
 	list_node_t* node;
 	list_node_t* next;
 
 	for(node=list->first; node!=NULL; node=next) {
 
+		if(node->flags&LINK_LIST_NODE_LOCKED)
+			break;
+
 		if(list->flags&LINK_LIST_ALWAYS_FREE || node->flags&LINK_LIST_MALLOC)
 			listFreeNodeData(node);
 
 		next = node->next;
 
 		free(node);
+
+		if(list->count)
+			list->count--;
 	}
 
-	list->first = NULL;
-	list->last = NULL;
-	list->count = 0;
+	list->first = node;
+	if(!list->count)
+		list->last = NULL;
+
+	return(list->count);
 }
 
-link_list_t* listFree(link_list_t* list)
+BOOL listFree(link_list_t* list)
 {
 	if(list==NULL)
-		return(NULL);
+		return(FALSE);
 
-	listFreeNodes(list);
+	if(listFreeNodes(list))
+		return(FALSE);
 
 	MUTEX_DESTROY(list);
 
 	if(list->flags&LINK_LIST_MALLOC)
-		free(list), list=NULL;
+		free(list);
 
-	return(list);
+	return(TRUE);
 }
 
-void listLock(link_list_t* list)
+void listLock(const link_list_t* list)
 {
 	MUTEX_LOCK(list);
 }
 
-void listUnlock(link_list_t* list)
+void listUnlock(const link_list_t* list)
 {
 	MUTEX_UNLOCK(list);
 }
@@ -302,6 +313,25 @@ void* listNodeData(const list_node_t* node)
 	return(node->data);
 }
 
+void listLockNode(list_node_t* node)
+{
+	if(node!=NULL)
+		node->flags|=LINK_LIST_NODE_LOCKED;
+}
+
+void listUnlockNode(list_node_t* node)
+{
+	if(node!=NULL)
+		node->flags&=~LINK_LIST_NODE_LOCKED;
+}
+
+BOOL listNodeIsLocked(const list_node_t* node)
+{
+	if(node!=NULL && node->flags&LINK_LIST_NODE_LOCKED)
+		return(TRUE);
+	return(FALSE);
+}
+
 static list_node_t* list_add_node(link_list_t* list, list_node_t* node, list_node_t* after)
 {
 	if(list==NULL)
@@ -338,7 +368,7 @@ list_node_t* listAddNode(link_list_t* list, void* data, list_node_t* after)
 {
 	list_node_t* node;
 
-	if(list==NULL)
+	if(list==NULL || data==NULL)
 		return(NULL);
 
 	if((node=(list_node_t*)malloc(sizeof(list_node_t)))==NULL)
@@ -355,7 +385,7 @@ long listAddNodes(link_list_t* list, void** data, list_node_t* after)
 	if(data==NULL)
 		return(-1);
 
-	for(i=0;data[i];i++)
+	for(i=0; data[i]!=NULL ;i++)
 		if((node=listAddNode(list,data[i],node==NULL ? after:node))==NULL)
 			return(i);
 
@@ -412,7 +442,7 @@ long listAddStringList(link_list_t* list, str_list_t str_list, list_node_t* afte
 	if(str_list==NULL)
 		return(-1);
 
-	for(i=0;str_list[i];i++)
+	for(i=0; str_list[i]!=NULL ;i++)
 		if((node=listAddNodeString(list,str_list[i],node==NULL ? after:node))==NULL)
 			return(i);
 
@@ -484,6 +514,9 @@ void* listRemoveNode(link_list_t* list, list_node_t* node)
 	if(node==NULL)
 		return(NULL);
 
+	if(node->flags&LINK_LIST_NODE_LOCKED)
+		return(NULL);
+
 	MUTEX_LOCK(list);
 
 	if(node->prev!=NULL)
@@ -523,7 +556,8 @@ long listRemoveNodes(link_list_t* list, list_node_t* node, long max)
 		node=list->first;
 
 	for(count=0; node!=NULL && count<max; node=node->next, count++)
-		listRemoveNode(list, node);
+		if(listRemoveNode(list, node)==NULL)
+			break;
 
 	MUTEX_UNLOCK(list);
 	
@@ -542,7 +576,7 @@ int main(int arg, char** argv)
 	link_list_t list;
 
 	listInit(&list,0);
-	for(i=0;i<100;i++) {
+	for(i=0; i<100; i++) {
 		sprintf(str,"%u",i);
 		listPushNodeString(&list,str);
 	}
diff --git a/src/xpdev/link_list.h b/src/xpdev/link_list.h
index 8af8b606c8..73875fe5b8 100644
--- a/src/xpdev/link_list.h
+++ b/src/xpdev/link_list.h
@@ -53,6 +53,7 @@ extern "C" {
 #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 */
+#define LINK_LIST_NODE_LOCKED	(1<<3)	/* Node is locked */
 
 typedef struct list_node {
 	void*				data;		/* pointer to some kind of data */
@@ -74,13 +75,13 @@ typedef struct link_list {
 
 /* Initialization, Allocation, and Freeing of Lists and Nodes */
 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);
+BOOL			listFree(link_list_t*);
+long			listFreeNodes(link_list_t*);
+BOOL			listFreeNodeData(list_node_t* node);
 
 /* Lock/unlock mutex-protoected linked lists */
-void			listLock(link_list_t*);
-void			listUnlock(link_list_t*);
+void			listLock(const link_list_t*);
+void			listUnlock(const link_list_t*);
 
 /* Return count or index of nodes, or -1 on error */
 long			listCountNodes(const link_list_t*);
@@ -107,6 +108,11 @@ list_node_t*	listNextNode(const list_node_t*);
 list_node_t*	listPrevNode(const list_node_t*);
 void*			listNodeData(const list_node_t*);
 
+/* Primitive node locking */
+void			listLockNode(list_node_t*);
+void			listUnlockNode(list_node_t*);
+BOOL			listNodeIsLocked(const list_node_t*);
+
 /* Add node to list, returns pointer to new node or NULL on error */
 list_node_t*	listAddNode(link_list_t*, void* data, list_node_t* after /* NULL=insert */);
 
-- 
GitLab