I would like to call pthread_join for a given thread id, but only if that thread has been started. The safe solution might be to add a variable to track which thread where s
This is an excellent question that I really wish would get more discussion in C++ classes and code tests.
One option for some systems-- which may seem like overkill to you, but has come in handy for me-- is to start a thread which does nothing other than efficiently wait for a tear-down signal, then quit. This thread stays running for the life of the application, going down very late in the shutdown sequence. Until that point, the ID of this thread can effectively be used as an "invalid thread" value-- or, more likely, as an "uninitialized" sentinel-- for most purposes. For example, my debug libraries typically track the threads from which mutexes were locked. This requires initialization of that tracking value to something sensible. Because POSIX rather stupidly declined to require that platforms define an INVALID_THREAD_ID, and because my libraries allow main() to lock things (making the pthread_self checks that are a good solution pthread_create unusable for lock tracking), this is the solution I have come to use. It works on any platform.
Note, however, that you have a little more design work to do if you want this to be able to initialize static thread references to invalid values.
Your assumption is incorrect to start with. pthread_t objects are opaque. You cannot compare pthread_t types directly in C. You should use pthread_equal instead.
Another consideration is that if pthread_create fails, the contents of your pthread_t will be undefined. It may not be set to your invalid value any more.
My preference is to keep the return values of the pthread_create calls (along with the thread IDs) and use that to determine whether each thread was started correctly.
I was porting some code that used pthreads into a C++ application, and I had the same question. I decided it was easier to switch to the C++ std::thread
object, which has the .joinable()
method to decide whether or not to join, i.e.
if (t.joinable()) t.join();
I found that just calling pthead_join
on a bad pthread_t value (as a result of pthread_create
failing) caused a seg fault, not just an error return value.
Unfortunately, on systems where pthread_t
is a pointer, pthread_equal()
can return equality even though the two args refer to different threads, e.g. a thread can exit and a new thread can be created with the same pthread_t
pointer value.
As suggested by Tony, you can use pthread_self()
in this situation.
But do not compare thread_t
s using ==
or !=
. Use pthread_equal.
From the pthread_self man page:
Therefore, variables of type pthread_t can't portably be compared using the C equality operator (==); use pthread_equal(3) instead.
I recently ran into this same issue. If pthread_create() failed, I ended up with a undefined, invalid value stored in my phtread_t structure. As a result, I keep a boolean associated with each thread that gets set to true if pthread_create() succeeded.
Then all I need to do is:
void* status;
if (my_thread_running) {
pthread_join(thread, &status);
my_thread_running = false;
}