Pregunta

I am a bit confused on how to declare a recursive mutex using pthread. What I try to do is have only one thread at a time be able to run a piece of code(including functions) but after scepticism I figured out that the use of mutexes would not work and that instead I should use recursive mutexes. Here is my code:

pthread_mutex_lock(&mutex);                   // LOCK

item = queue_peek(queue);                     // get last item in queue
item_buff=item;                               // save item to a buffer
queue_removelast(queue);                      // remove last item from queue

pthread_mutex_unlock(&mutex);                 // UNLOCK

So what I try to do is just read/remove from the queue serially.

The thing is that there isn't any example out there on how to declare recursive mutexes. Or there maybe a few but they don't compile for me.

¿Fue útil?

Solución

The code from Michael Foukarakis is almost good but he initializes the mutex twice which leads to undefined behavior. It should just be:

pthread_mutex_t Mutex;
pthread_mutexattr_t Attr;

pthread_mutexattr_init(&Attr);
pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&Mutex, &Attr);

I actually use this code in production, and I know it works correctly on Linux, Solaris, HP-UX, AIX, Mac OSX and FreeBSD.

You also need to add proper linker flag to compile this:

AIX, Linux, FreeBSD:
CPLATFORM += -pthread

mingw32:
LDFLAGS += -lpthread

Otros consejos

To create a recursive mutex, use:

#include <pthread.h>
int pthread_mutexatttr_settype(pthread_mutexattr_t *attr,
                               int type);

where type is PTHREAD_MUTEX_RECURSIVE.

Don't forget to check the return value!

Example:

/* or PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */
pthread_mutex_t       mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutexattr_t   mta;

or alternatively, initialize at runtime (don't do both, it's undefined behaviour):

pthread_mutexattr_init(&mta);
/* or PTHREAD_MUTEX_RECURSIVE_NP */
pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE);

pthread_mutex_init(&mutex, &mta);

On Linux (but this is non portable to other systems), if the mutex is a global or static variable, you could initialize it like

static pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;

(and by the way, the example is from pthread_mutex_init(3) man pages!)

You need to add mutex attributes when creating the mutex.

Call pthread_mutexattr_init, then pthread_mutexattr_settype with PTHREAD_MUTEX_RECURSIVE then use these attributes with pthread_mutex_init. Read man pthread_mutexattr_init for more info.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top