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