Unix Threads (Basics)

Discussion in 'C' started by poornaMoksha, Sep 18, 2011.

  1. poornaMoksha

    poornaMoksha New Member

    Joined:
    Jan 29, 2011
    Messages:
    150
    Likes Received:
    33
    Trophy Points:
    0
    Occupation:
    Software developer
    Location:
    India
    At times certain tasks need more time to execute and when multiple such tasks are desired then blocking on a single task is not a good practice. To Understand, Think of a program that provides some service but this service takes time to execute. Now, if you want this service again and again then every time you may need to wait for the previous request to get complete before you can submit your request which means you even cannot put forward your request until the last request is complete.

    Example



    For example, the following program asks the user to enter his/her name and does some processing that takes some time. The program commits to serve 5 persons at a time.

    Code:
    #include<stdio.h>
    #include<string.h>
    
    void doSomeTimConsumingStuff(char* buff)
    {
    	unsigned long i = 0;
    
    	/** Simulating some time consuming stuff **/
    	for(i=0; i<(0xFFFFFFFF);i++);
    
    	printf("\n Mr/Ms %s, your work done\n", buff);
    }
    
    int main(void)
    {
    	int i = 0;
    
    	while(i < 5) // Commiting to serve 5 persons at a time.
    	{
    		char buff[100];
    		memset(buff,'0',sizeof(buff));
    		printf("\n Enter your name :");
    		scanf("%s",buff); // Use of scanf is discouraged as it opens doors for buffer overflow. Using it for demo purpose only.
    
    		doSomeTimConsumingStuff(buff);
    		i++;
    	}
    	return 0;
    }
    
    The problem with above program is that It cannot serve the next person until it is done serving the previous one. So we can say that the call to the function 'doSomeTimConsumingStuff()' is blocking.

    The output of the above program is :

    Code:
    Enter your name :abc
    
     Mr/Ms abc, your work done
    
     Enter your name :efg
    
     Mr/Ms efg, your work done
    
     Enter your name :ijk
    
     Mr/Ms ijk, your work done
    
     Enter your name :lmn
    
     Mr/Ms lmn, your work done
    
     Enter your name opq
    
     Mr/Ms opq, your work done
    So now here is an example situation where we can use a concept known as threads. Though with a single processor system the taks will be done serially(at the processor level) but with the help of threads we can make the call to function 'doSomeTimConsumingStuff()' asynchronus by running it in a different thread everytime. So for the users it may seem that their requests are being handled parallely.

    For example, the above program can be re-written as :

    Code:
    #include<stdio.h>
    #include<string.h>
    #include<pthread.h>
    #include<stdlib.h>
    
    void* doSomeTimConsumingStuff(void* buff)
    {
    	/** Simulating some time consuming stuff **/
    	unsigned long i = 0;
    
    	for(i=0; i<(0xFFFFFFFF);i++);
    
    	printf("\n ----------------------------------------> Mr/Ms %s, your work done\n", (char*)buff);
    
    	free(buff);
    	return NULL;
    }
    
    int main(void)
    {
    	int i = 0;
    	int j = 0;
    	pthread_t tid[5];
    	int err;
    	void* tret = NULL;
    
    	while(i < 5)
    	{
    		char *buff = (char*)malloc(100);
    		memset(buff,'0',sizeof(100));
    
    		printf("\n Enter your name :");
    		scanf("%s",buff);
    
    		err = pthread_create(&(tid[i]), NULL, &doSomeTimConsumingStuff, buff);
    		if (err != 0)
    			printf("\ncan't process your request: %s\n", strerror(err));
    		else
    			printf("\n Thanks Mr/Ms [%s] for the request, your request is under processing, will notify you when its done\n", buff);
    
    		i++;
    	}
    	for(j = 0;j<5;j++)
    	{
    		err = pthread_join(tid[j], &tret);
    		if (err != 0)
    			printf("\n can't process the request: %s\n", strerror(err));
    	}
    
    	return 0;
    }
    
    In the above program, the program takes the input, notifies that the request is under processing by creating a new thread and is ready to accept another request. So the user is not blocked while providing input.

    The output of the above program comes out as :

    Code:
    Enter your name :abc
    
     Thanks Mr/Ms [abc] for the request, your request is under processing, will notify you when its done
    
     Enter your name :efg
    
     Thanks Mr/Ms [efg] for the request, your request is under processing, will notify you when its done
    
     Enter your name :ijk
    
     Thanks Mr/Ms [ijk] for the request, your request is under processing, will notify you when its done
    
     Enter your name :lmn
    
     Thanks Mr/Ms [lmn] for the request, your request is under processing, will notify you when its done
    
     Enter your name opq
    
     Thanks Mr/Ms [opq] for the request, your request is under processing, will notify you when its done
    
     ----------------------------------------> Mr/Ms efg, your work done
    
     ----------------------------------------> Mr/Ms abc, your work done
    
     ----------------------------------------> Mr/Ms lmn, your work done
    
     ----------------------------------------> Mr/Ms ijk, your work done
    
     ----------------------------------------> Mr/Ms opq, your work done
    So, as you can see above, the user is not blocked to provide input.

    Change Set



    So, we made our program asynchronus from synchronus and the steps involved were
    • Include the header 'pthread.h'.
    • Changed the signature of the function 'doSomeTimConsumingStuff()' from void doSomeTimConsumingStuff(char*) to void* doSomeTimConsumingStuff(void*) as the pthread_create API requires a pointer to (void*)(*)(void*) kind of a function.
    • Introduced a call to 'pthread_create()' that creates a new thread.
    • Introduced a call to 'pthread_join()' that makes sure that the parent thread (Original thread in which main() is being run) does not get over before all the threads created by pthread_create() are done with their respective processing.
    • Last but not the least, compile the program with '-lpthread' flag in order to link to pthread library.
    For details about thread APIs, Will write an article on that too. Stay tuned for more...
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice