Skip to content
Snippets Groups Projects
Commit 1b436de2 authored by rswindell's avatar rswindell
Browse files

Building with LINK_LIST_THREADSAFE now enables optional linked-list

attached semaphore (automatically created/destroyed with list and posted when
nodes are added) - with new listSemWait... functions.
Added list-attached private data pointer (with get/set functions).
Fixed MUTEX_LOCK/UNLOCK calls in listSubStringList().
Fixed MUTEX_* macros (const mismatch) in thread-safe Win32 build.
parent d9a98c6d
No related branches found
No related tags found
No related merge requests found
......@@ -40,11 +40,10 @@
#include "link_list.h"
#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); }
#define MUTEX_INIT(list) { if(list->flags&LINK_LIST_MUTEX) pthread_mutex_init((pthread_mutex_t*)&list->mutex,NULL); }
#define MUTEX_DESTROY(list) { if(list->flags&LINK_LIST_MUTEX) pthread_mutex_destroy((pthread_mutex_t*)&list->mutex); }
#define MUTEX_LOCK(list) { if(list->flags&LINK_LIST_MUTEX) pthread_mutex_lock((pthread_mutex_t*)&list->mutex); }
#define MUTEX_UNLOCK(list) { if(list->flags&LINK_LIST_MUTEX) pthread_mutex_unlock((pthread_mutex_t*)&list->mutex); }
#else
#define MUTEX_INIT(list)
#define MUTEX_DESTROY(list)
......@@ -66,6 +65,11 @@ link_list_t* listInit(link_list_t* list, long flags)
MUTEX_INIT(list);
#if defined(LINK_LIST_THREADSAFE)
if(list->flags&LINK_LIST_SEMAPHORE)
sem_init(&list->sem,0,0);
#endif
return(list);
}
......@@ -118,12 +122,74 @@ BOOL listFree(link_list_t* list)
MUTEX_DESTROY(list);
#if defined(LINK_LIST_THREADSAFE)
if(list->sem!=NULL) {
sem_destroy(&list->sem);
list->sem=NULL;
}
#endif
if(list->flags&LINK_LIST_MALLOC)
free(list);
return(TRUE);
}
void* listSetPrivateData(link_list_t* list, void* p)
{
void* old;
if(list==NULL)
return(NULL);
old=list->private_data;
list->private_data=p;
return(old);
}
void* listGetPrivateData(link_list_t* list)
{
if(list==NULL)
return(NULL);
return(list->private_data);
}
#if defined(LINK_LIST_THREADSAFE)
BOOL listSemPost(const link_list_t* list)
{
if(list==NULL)
return(FALSE);
return(sem_post(&list->sem)==0);
}
BOOL listSemWait(const link_list_t* list)
{
if(list==NULL)
return(FALSE);
return(sem_wait(&list->sem)==0);
}
BOOL listSemTryWait(const link_list_t* list)
{
if(list==NULL)
return(FALSE);
return(sem_trywait(&list->sem)==0);
}
BOOL listSemTryWaitBlock(const link_list_t* list, unsigned long timeout)
{
if(list==NULL)
return(FALSE);
return(sem_trywait_block(&list->sem,timeout));
}
#endif
#if defined(__BORLANDC__)
#pragma argsused
#endif
......@@ -214,14 +280,14 @@ str_list_t listSubStringList(const list_node_t* node, long max)
if((str_list=strListInit())==NULL)
return(NULL);
MUTEX_LOCK(list);
MUTEX_LOCK(node->list);
for(count=0; count<max && node!=NULL; node=node->next) {
if(node->data!=NULL)
strListAppend(&str_list, (char*)node->data, count++);
}
MUTEX_UNLOCK(list);
MUTEX_UNLOCK(node->list);
return(str_list);
}
......@@ -373,6 +439,9 @@ static list_node_t* list_add_node(link_list_t* list, list_node_t* node, list_nod
MUTEX_UNLOCK(list);
if(list->sem!=NULL)
listSemPost(list);
return(node);
}
......
......@@ -42,7 +42,8 @@
#include "str_list.h" /* string list functions and types */
#if defined(LINK_LIST_THREADSAFE)
#include "threadwrap.h"
#include "threadwrap.h" /* mutexes */
#include "semwrap.h" /* semaphores */
#endif
#if defined(__cplusplus)
......@@ -55,24 +56,27 @@ 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_NEVER_FREE (1<<2) /* NEVER free node data when removing */
#define LINK_LIST_MUTEX (1<<3) /* Mutex protected linked-list */
#define LINK_LIST_NODE_LOCKED (1<<4) /* Node is locked */
#define LINK_LIST_MUTEX (1<<3) /* Mutex-protected linked-list */
#define LINK_LIST_SEMAPHORE (1<<4) /* Semaphore attached to linked-list */
#define LINK_LIST_NODE_LOCKED (1<<5) /* Node is locked */
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) */
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 */
unsigned long flags; /* private use flags */
} list_node_t;
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 */
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 */
void* private_data; /* for use by the application only */
#if defined(LINK_LIST_THREADSAFE)
pthread_mutex_t mutex;
sem_t sem;
#endif
} link_list_t;
......@@ -82,6 +86,11 @@ BOOL listFree(link_list_t*);
long listFreeNodes(link_list_t*);
BOOL listFreeNodeData(list_node_t* node);
BOOL listSemPost(const link_list_t*);
BOOL listSemWait(const link_list_t*);
BOOL listSemTryWait(const link_list_t*);
BOOL listSemTryWaitBlock(const link_list_t*, unsigned long timeout);
/* Lock/unlock mutex-protected linked lists (no-op for unprotected lists) */
void listLock(const link_list_t*);
void listUnlock(const link_list_t*);
......@@ -90,6 +99,10 @@ void listUnlock(const link_list_t*);
long listCountNodes(const link_list_t*);
long listNodeIndex(const link_list_t*, list_node_t*);
/* Get/Set list private data */
void* listSetPrivateData(link_list_t*, void*);
void* listGetPrivateData(link_list_t*);
/* Return an allocated string list (which must be freed), array of all strings in linked list */
str_list_t listStringList(const link_list_t*);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment