Reputation: 6953
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
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
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
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
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