When pthread_create() is successful, the ID of the thread created is stored in the location referred to as tid.
Creating a thread using a NULL attribute argument has the same effect as using a default attribute; both create a default thread. When tattr is initialized, it acquires the default behavior.
Return Values
pthread_create() returns zero when it completes successfully. Any other return value indicates that an error occurred. When any of the following conditions are detected, pthread_create() fails and returns the corresponding value.
A system limit is exceeded, such as when too many LWPs have been created.
The value of tattr is invalid.
Wait for Thread Termination
pthread_join(3THR)
Use pthread_join(3THR) to wait for a thread to terminate.
Prototype: int pthread_join(thread_t tid, void **status); |
#include <pthread.h> pthread_t tid; int ret; void *status; /* waiting to join thread "tid" with status */ ret = pthread_join(tid, &status); /* waiting to join thread "tid" without status */ ret = pthread_join(tid, NULL); |
The pthread_join() function blocks the calling thread until the specified thread terminates.
The specified thread must be in the current process and must not be detached. For information on thread detachment, see "Set Detach State".
When status is not NULL, it points to a location that is set to the exit status of the terminated thread when pthread_join() returns successfully.
If multiple threads wait for the same thread to terminate, they all wait until the target thread terminates, than one thread returns successfully and the others fail with an error of ESRCH.
After pthread_join() returns, any data storage associated with the thread can be reclaimed by the application.
Return Values
pthread_join() returns zero when it completes successfully. Any other return value indicates that an error occurred. When any of the following conditions are detected, pthread_join() fails and returns the corresponding value.
tid is not a valid, undetached thread in the current process.
A deadlock would exist, such as a thread waits for itself or thread A waits for thread B and thread B waits for thread A.
The value of tid is invalid.
Remember that pthread_join() works only for target threads that are nondetached. When there is no reason to synchronize with the termination of a particular thread, then that thread should be detached.
A Simple Threads Example
In Example 2-1, one thread executes the procedure at the top, creating a helper thread that executes the procedure fetch(), which involves a complicated database lookup and might take some time.
The main thread wants the results of the lookup but has other work to do in the meantime. So it does those other things and then waits for its helper to complete its job by executing pthread_join().
An argument, pbe, to the new thread is passed as a stack parameter. This can be done here because the main thread waits for the spun-off thread to terminate. In general, though, it is better to use malloc(3C) to allocate storage from the heap instead of passing an address to thread stack storage, because this address might disappear or be reassigned if the thread terminated.
Example 2-1 A Simple Threads Program
Detaching a Thread
pthread_detach(3THR)
pthread_detach(3THR) is an alternative to pthread_join(3THR) to reclaim storage for a thread that is created with a detachstate attribute set to PTHREAD_CREATE_JOINABLE.
Prototype: int pthread_detach(thread_t tid); |
#include <pthread.h> pthread_t tid; int ret; /* detach thread tid */ ret = pthread_detach(tid); |
The pthread_detach() function is used to indicate to the implementation that storage for the thread tid can be reclaimed when the thread terminates. If tid has not terminated, pthread_detach() does not cause it to terminate. The effect of multiple pthread_detach() calls on the same target thread is unspecified.
Return Values
pthread_detach() returns zero when it completes successfully. Any other return value indicates that an error occurred. When any of the following conditions is detected, pthread_detach() fails and returns the corresponding value.
tid is not a valid thread.
tid is not a valid, undetached thread in the current process.
Create a Key for Thread-Specific Data
Single-threaded C programs have two basic classes of data--local data and global data. For multithreaded C programs a third class is added--thread-specific data (TSD). This is very much like global data, except that it is private to a thread.
Thread-specific data is maintained on a per-thread basis. TSD is the only way to define and refer to data that is private to a thread. Each thread-specific data item is associated with a key that is global to all threads in the process. Using the key, a thread can access a pointer (void *) that is maintained per-thread.
pthread_key_create(3THR)
Use pthread_key_create(3THR) to allocate a key that is used to identify thread-specific data in a process. The key is global to all threads in the process, and all threads initially have the value NULL associated with the key when it is created.
Call pthread_key_create() once for each key before using the key. There is no implicit synchronization.
Once a key has been created, each thread can bind a value to the key. The values are specific to the threads and are maintained for each thread independently. The per-thread binding is deallocated when a thread terminates if the key was created with a destructor function.
Prototype: int pthread_key_create(pthread_key_t *key, void (*destructor) (void *)); |
#include <pthread.h> pthread_key_t key; int ret; /* key create without destructor */ ret = pthread_key_create(&key, NULL); /* key create with destructor */ ret = pthread_key_create(&key, destructor); |
When pthread_key_create() returns successfully, the allocated key is stored in the location pointed to by key. The caller must ensure that the storage and access to this key are properly synchronized.