c++ - standard - Initializing pthread mutexes




standard c mutex (4)

According to the documentation a mutex can be initialized in two ways:

Using the init function:

pthread_mutex_t theMutex;
pthread_mutex_init(&theMutex, NULL);

Using an initializer macro:

pthread_mutex_t result = PTHREAD_MUTEX_INITIALIZER;

About the latter the documentation says:

In cases where default mutex attributes are appropriate, the macro PTHREAD_MUTEX_INITIALIZER can be used to initialize mutexes that are statically allocated. The effect shall be equivalent to dynamic initialization by a call to pthread_mutex_init() with parameter attr specified as NULL, except that no error checks are performed.

Does this mean that it may only be used for static variables and not for local variables?

C++ Specific

I wanted to use the following "factory function":

static pthread_mutex_t GetFastNativeMutex()
{
    static pthread_mutex_t result = PTHREAD_MUTEX_INITIALIZER;
    return result;
}

Because it would allow me to initialize mutexes in a C++ initializer list as follows:

MyClass() : myMutex(GetFastNativeMutex()) {}

Is this valid? (Btw in practice it works. Valgrind also doesn't complain.)

Update

If I understood the documentation correctly then this should be ok:

#include <pthread.h>

static pthread_mutex_t m0 = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;

However, when looking at the preprocessor output (using gcc -E main.cpp) I see the following:

static pthread_mutex_t m0 = {0x32AAABA7, {0}};
static pthread_mutex_t m1 = {0x32AAABA7, {0}};
static pthread_mutex_t m2 = {0x32AAABA7, {0}};

It turns out that three times the same mutex was created. What am I doing wrong here?


It "works" if all myMutex instances should share the same POSIX mutex. You currently have one mutex and not one per MyClass object. This is most certainly not what you want, isn't?


Just because you can do it, doesn't mean you should.

The documentation clearly specifies that you use pthread_mutex_init at runtime and the other macro for statically allocated mutexes, I don't see any reason for not doing so.


Standard does not allow to copy mutexes by value or return them by value. See http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_mutex_init.html, the paragraph that explicitly talks about this, saying "IEEE Std 1003.1-2001 does not define assignment or equality for this type [pthread_mutex_t]"

The closest relative of pthread_mutex, WIN32 CriticalSection, is absolutely not copyable and not returnable by value. So your API will be very nonportable anyway.

I recommend against copying(returning) mutex by value even you can test it and it works.

Note that initializing a mutex is different from copying already initialized mutex.


Your GetFastNativeMutex is in no way a factory function. It always returns the copy of the same mutex, the point of factory is to abstract allocation and creation of a new object, not to reuse the same one all the time. So no, this is not valid for any usage that wouldn't be done by using the same mutex as a global variable.

A quote from here:

The result of referring to copies of mutex in calls to pthread_mutex_lock(), pthread_mutex_trylock(), pthread_mutex_unlock(), and pthread_mutex_destroy() is undefined





c