Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PTHREAD_MUTEX_INITIALIZER inside C++ member function cannot compile?

Tags:

c++

pthreads

class A {
    public:
        A();
    private:
        pthread_mutex_t mu;
};

A::A()
{
    mu = PTHREAD_MUTEX_INITIALIZER;  //cannot compile
}

Can't I initialize pthread_mutex_t inside a class member function?

like image 331
Alcott Avatar asked Jul 26 '12 09:07

Alcott


3 Answers

Instead of this:

A::A()
{
    mu = PTHREAD_MUTEX_INITIALIZER;  //cannot compile
}

Try this:

A::A()
{
pthread_mutex_init( &(mu), NULL);
}

The PTHREAD_MUTEX_INITIALIZER is a macro,a C struct initializer for something like {0,0,0,0,0{0}} and can only be used at the point of definition.

like image 195
askmish Avatar answered Nov 07 '22 02:11

askmish


Use pthread_mutex_init in this case, as the constant is for compile-time initialization.

like image 25
Diego Sevilla Avatar answered Nov 07 '22 02:11

Diego Sevilla


Even if we change this to use an initializer list in the constructor it still fails:

#include <pthread.h>

struct foo {
  pthread_mutex_t test;
  foo() : test(PTHREAD_MUTEX_INITIALIZER) {}
};

int main() {
  foo f;
}

We can see why it fails and an only be used for initialisation in a few contexts by looking at the output from the pre-processsor:

struct foo {
  pthread_mutex_t test;
  foo() : test({ { 0, 0, 0, 0, 0, { 0 } } }) {}
};

It's not legal to use nested braces for initialisation like that in C++03, but what's more interesting perhaps is that C++11 makes this syntax and usage perfectly legal.

In your original code we can see a few more things:

A::A()
{
    const pthread_mutex_t test = PTHREAD_MUTEX_INITIALIZER; //  initialization - fine
    mu = test; // assignment - fine
    mu = PTHREAD_MUTEX_INITIALIZER;  // assignment - C++11 only
}
like image 36
Flexo Avatar answered Nov 07 '22 04:11

Flexo