Tuesday, May 10, 2011

Basic pthread example 3

Following pthread example is collected from  http://timmurphy.org/2010/05/04/pthreads-in-c-a-minimal-working-example/ It shows basic mechanism of pthread programming and a minimal pthread example.

-------------------------------- Quoted ---------------------------------------
Pthreads are a simple and effective way of creating a multi-threaded application. This introduction to pthreads shows the basic functionality – executing two tasks in parallel and merging back into a single thread when the work has been done.
First I’ll run through the basics of threading applications with pthreads. Multi-threaded applications allow two or more tasks to be executed concurrently (ie: at the same time). When a thread is created using pthread_create, both the original thread and the new thread share the same code base and the same memory – it’s just like making two function calls at the same time. Multi-threaded applications come with a whole host of concurrency issues, which will be discussed further in a future post.
All C programs using pthreads need to include the pthread.h header file (ie: #include <pthread.h>). There are four steps to creating a basic threaded program:
1: Define thread reference variables
The variable type pthread_t is a means of referencing threads. There needs to be a pthread_t variable in existence for every thread being created. Something like pthread_t thread0; will do the trick.
2: Create an entry point for the thread
When creating a thread using pthreads, you need to point it to a function for it to start execution. The function must return void * and take a single void * argument. For example, if you want the function to take an integer argument, you will need to pass the address of the integer and dereference it later. This may sound complicated but, as is shown below, it’s pretty simple. An example function signature would be void *my_entry_function(void *param);
3: Create the thread
Once the pthread_t variable has been defined and the entry point function created, we can create the thread using pthread_create. This method takes four arguments: a pointer to the pthread_t variable, any extra attributes (don’t worry about this for now – just set it to NULL), a pointer to the function to call (ie: the name of the entry point) and the pointer being passed as the argument to the function. Now there’s a lot of pointers in that call, but don’t stress – it’s not as tricky as it sounds. This call will look something like pthread_create(&thread0, NULL, my_entry_function, &parameter);
4: Join everything back up
When the newly-created thread has finished doing it’s bits, we need to join everything back up. This is done by the pthread_join function which takes two parameters: the pthread_t variable used when pthread_create was called (not a pointer this time) and a pointer to the return value pointer (don’t worry about this for now – just set it to NULL). This call will look something like pthread_join(thread0, NULL);
And that’s all there is to it. The function used as the thread entry point can call other functions, create variables or do anything any other function can do. It can also use the variables set by the other thread.
When compiling the program, you will also need to add -lpthread to the compile command. ie: gcc program.c -o program -lpthread
Below is a minimum example of a threaded application. It creates two numbers, x and y, and creates a second thread. The first thread increments y until it has the value of 100, while the second thread increments x until it has the value of 100 at the same time. When this is done, it joins the second thread back with the main program and prints the results. Note how, even though x was changed by the second thread, it has been changed for the main program too!

#include <pthread.h>
#include <stdio.h>

/* this function is run by the second thread */
void *inc_x(void *x_void_ptr)
{

/* increment x to 100 */
int *x_ptr = (int *)x_void_ptr;
while(++(*x_ptr) < 100);
printf("x increment finished\n");
/* the function must return something - NULL will do */
return NULL;
}
int main()
{

int x = 0, y = 0;
/* show the initial values of x and y */
printf("x: %d, y: %d\n", x, y);
/* this variable is our reference to the second thread */
pthread_t inc_x_thread;
/* create a second thread which executes count_x(&x) */
if(pthread_create(&inc_x_thread, NULL, inc_x, &x)) {
fprintf(stderr, "Error creating thread\n");
return 1;
}
/* increment y to 100 in the first thread */
while(++y < 100);
printf("y increment finished\n");
/* wait for the second thread to finish */
if(pthread_join(inc_x_thread, NULL)) {
fprintf(stderr, "Error joining thread\n");
return 2;
}
/* show the results - x is now 100 thanks to the second thread */
printf("x: %d, y: %d\n", x, y);
return 0;
}