PThreads thread management
These are all the functions which start with either pthread_ or pthread_attr_. These functions all apply to threads themselves and their attribute objects.
The basic use of threads with Pthreads looks like the following:
#include <pthread.h>
#include <stdlib.h>
#define NUM_THREADS 5
The main Pthreads header is pthread.h. This gives access to everything but semaphores (covered later in this section). We also define a constant for the number of threads we wish to start here:
void* worker(void* arg) {
int value = *((int*) arg);
// More business logic.
return 0;
}
We define a simple Worker function, which we'll pass to the new thread in a moment. For demonstration and debugging purposes one could first add a simple cout or printf-based bit of business logic to print out the value sent to the new thread.
Next, we define the main function as follows:
int main(int argc, char** argv) {
pthread_t threads[NUM_THREADS];
int thread_args[NUM_THREADS];
int result_code;
for (unsigned int i = 0; i < NUM_THREADS; ++i) {
thread_args[i] = i;
result_code = pthread_create(&threads[i], 0, worker, (void*) &thread_args[i]);
}
We create all of the threads in a loop in the preceding function. Each thread instance gets a thread ID assigned (first argument) when created in addition to a result code (zero on success) returned by the pthread_create() function. The thread ID is the handle to reference the thread in future calls.
The second argument to the function is a pthread_attr_t structure instance, or 0 if none. This allows for configuration characteristics of the new thread, such as the initial stack size. When zero is passed, default parameters are used, which differ per platform and configuration.
The third parameter is a pointer to the function which the new thread will start with. This function pointer is defined as a function which returns a pointer to void data (that is, custom data), and accepts a pointer to void data. Here, the data being passed to the new thread as an argument is the thread ID:
for (int i = 0; i < NUM_THREADS; ++i) {
result_code = pthread_join(threads[i], 0);
}
exit(0);
}
Next, we wait for each worker thread to finish using the pthread_join() function. This function takes two parameters, the ID of the thread to wait for, and a buffer for the return value of the Worker function (or zero).
Other functions to manage threads are as follows:
- void pthread_exit(void *value_ptr):
This function terminates the thread calling it, making the provided argument's value available to any thread calling pthread_join() on it.
- int pthread_cancel(pthread_t thread):
This function requests that the specified thread will be canceled. Depending on the state of the target thread, this will invoke its cancellation handlers.
Beyond this, there are the pthread_attr_* functions to manipulate and obtain information about a pthread_attr_t structure.