lornova
lornova

Reputation: 6953

Correct pthread_t initialization and handling

I understand that pthread_t should be treated as an opaque value, however I don't know how to initialize it when used as a class member, and how can I check for its validity.

Consider this code sample:

class MyClass
{
public:
    pthread_t thread;

    MyClass()
        : thread(0) // Wrong because pthread_t should be an opaque value,
                    // so how should I initialize it?
    {}

    ~MyClass()        
    {
        if( thread ) // Wrong, but how can I verify if it is valid?
            pthread_join(thread, NULL);
    }
};

I also understand that if pthread_create() fails, the pthread_t value may be inconsistent. So I should only rely on the return value from pthread_create(). But this means that I should keep this returned value along with pthread_t and use it to check thread validity? And in this case, how should I initialize in the class constructor this value?

class MyClass
{
public:
    pthread_t thread;
    int threadValid;

    MyClass()
        : thread(0), // Wrong because pthread_t should be an opaque value,
                     // so how should I initialize it?
        , threadValid(1) // pthread_create return zero in case of success,
                         // so I can initialize this to any nonzero value?
    {}

    ~MyClass()        
    {
        if( threadValid == 0 ) // Nonzero means thread invalid.
                               // Is this the correct approach?
        {
            pthread_join(thread, NULL);
            threadValid = 1;
        }
    }
};

I have a Windows API background, and there a thread has its HANDLE value, which may be initialized safely to NULL, and can be checked against NULL, and if CreateThread() fails, it just consistently returns NULL. There's no way, with pthreads, to keep this neat and simple approach?

Upvotes: 5

Views: 17911

Answers (4)

Jonas Byström
Jonas Byström

Reputation: 26189

pthread_t   thread_handle;
pthread_attr_t  thread_attributes;

pthread_attr_init(&thread_attributes);
pthread_attr_setdetachstate(&thread_attributes, PTHREAD_CREATE_JOINABLE);

threadValid = (::pthread_create(&thread_handle, &thread_attributes, function, data) == 0);

and when shutting it down:

if (threadValid) {
    ::pthread_join(thread_handle, 0);
}

Don't start your thread in the constructor though.

Upvotes: 1

Per Johansson
Per Johansson

Reputation: 6887

But this means that I should keep this returned value along with pthread_t and use it to check thread validity?

Yes, or more simply keep a boolean, like already mentioned.

And in this case, how should I initialize in the class constructor this value?

Don't initialize it, it's not mandatory to initialize members in C++.

Upvotes: 5

Giordano
Giordano

Reputation: 311

Unfortunately you can only use a guard variable to know if its value make sense or not. So for instance you can't use 0 because it would be a valid pthread_t on some systems (DG/UX for instance). You should have to use something else to know if the value can be used or not, and you should value-initialize it.

If you can compromise on portability (non production code for instance), consider that on Linux and Android pthread_t should be like an int type, and on Darwin it should be an handle, so it would work if you initialize it to 0.

Upvotes: 3

ecatmur
ecatmur

Reputation: 157484

pthread_t is a C type, so it must have a trivial default constructor; so you can just value-initialize it:

    : thread(), // ...

Your usage of threadValid seems somewhat confused. It would be better to make it a bool initially set to false and then only set it true once pthread_create succeeds.

Upvotes: 10

Related Questions