Thread: Basic Multi-threading

  1. #1
    Registered User
    Join Date
    Jun 2008
    Posts
    15

    Basic Multi-threading

    I'm developing a basic multi-threaded application, I have never worked with threads and semaphores before. The main program calls thread1 to read input from standard input, every time input is entered that thread than calls thread2 to process it. Than thread2 calls the thread3 to display the results. Thread1 must wait until thread2 and thread3 are done. Thread 1 also needs to be able to tell the other threads to shut down on system exit. I was thinking of using semaphores to implement synchronization since the threads will always run in that order, 1,2,3. Can anyone help me out, this is what i have so far. Any links to implementing semaphores would be great too.

    p.s. other threads haven't been implemented yet

    Code:
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <semaphore.h>
    
    //Macro
    #define NUM_THREADS 3
    #define BUFFSIZE 81
    
    //Type
    typedef enum { FALSE, TRUE } boolean;
    
    //Function prototypes
    void *input( void *id );
    
    //Globals (shared data)
    char *operator1;
    
    int operand1, operand2, result;
    
    int main( int argc, char *argv[] )
    {
    	pthread_t threads[ NUM_THREADS ];
    
    	int ret_code;
    	long id = 1;
    
    	ret_code = pthread_create( &threads[0], NULL, input, (void *)id );
    
    	if( ret_code )
    	{
    		printf( "\nERROR! Could not create thread, error code %d returned", ret_code );
    		exit(-1);
    	}
    
    	pthread_exit( NULL );
    }
    
    void *input( void *id )
    {
    	char buffer[ BUFFSIZE ]; // room for 80 chars plus \0
    	char *input;
    
    	printf( "$>" );
      	input = fgets( buffer, BUFFSIZE, stdin ); //read input from console
    
      	//Keep getting input from console until a string contains the letter
      	//q upper or lower case
    	while( input != NULL && strstr( input, "q" ) == NULL && strstr( input, "Q" ) == NULL )
      	{
    		//Format of string will be error free and
    		//in the format 'operand operator operand'
    		//convert operand's to integers
    		operand1 = atoi( strtok( input, " " ) ); //write first operand to shared data
    		operator1 = strtok( NULL, " " );         //write operator to shared data
    		operand2 = atoi( strtok( NULL, " " ) );    //write second operand to shared data
    
    		//Signal thread2 to start processing, than wait until thread3
                    //has finished so we can restart the entire process again
    
    		//Next line
    		printf( "$>" );
    	 	input = fgets( buffer, BUFFSIZE, stdin );
    	}
    
    	//Quit command entered, signal other threads to exit and shut down
    
    	pthread_exit( NULL );
    }
    I'm not 100% sure if I should create the other threads within the 'main' program or not, I guess I have to, but block them and allow thread1 to unblock them?

  2. #2
    Chinese pâté foxman's Avatar
    Join Date
    Jul 2007
    Location
    Canada
    Posts
    404
    Well, first of all, the way you are describing your problem, multi-threading doesn't seem to have any advantages. You are describing a purely sequential execution scheme.

    But if you still want to use threads, well, using mutexes is one way to reach your goal. Here's a backbone of what it could looks like
    Code:
    pthread_mutex_t mutex0 = PTHREAD_MUTEX_INITIALIZER;
    pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
    pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
    
    void* thread1Func(void *)
    {
       while (1)
       {
          pthread_mutex_lock(&mutex1);
          // Do some stuff
          // Pass argument to "thread2" via another global variable
          pthread_mutex_unlock(&mutex2);
       }   
    }
    
    void* thread2Func(void *)
    {
       while (1)
       {
          pthread_mutex_lock(&mutex2);
          // Do some other stuff
          pthread_mutex_unlock(&mutex0);
       }   
    }
    
    int main()
    {
       pthread_t thread1, thread2;
    
       // Since mutex are initially unlocked, we lock them...
       pthread_mutex_lock(&mutex0);
       pthread_mutex_lock(&mutex1);
       pthread_mutex_lock(&mutex2);
    
       // Creating thread...
       pthread_create(&thread1, NULL, thread1Func, NULL);
       pthread_create(&thread2, NULL, thread2Func, NULL);
    
       while (1)
       {
          // Read user input, break the loop when there's nothing more to read...
          // Pass argument to "thread1" via a global variable
         pthread_mutex_unlock(&mutex1);
         pthread_mutex_lock(&mutex0);
       }
    }
    I bet there is more elegant way to use pthread. But I don't know it well me neither...

    Oh and by the way, when main return, every threads close automatically, so you don't have to worry.
    I hate real numbers.

  3. #3
    Registered User
    Join Date
    Jun 2008
    Posts
    15
    Ya I know what you mean, i'm just trying to get a feel for threads. I thought about using a mutex but wanted to explore using a semaphore, to allow a sequential flow. But a semaphore would probably be exactly the same thing as a mutex right? I mean instead of doing the locks and unlocks I would just be checking my semaphore? So I would just be writing
    signal( semaphore ) and wait( semaphore ) instead? Just trying to get an idea of what semaphores are all about.

  4. #4
    Chinese pâté foxman's Avatar
    Join Date
    Jul 2007
    Location
    Canada
    Posts
    404
    Well yeah, a mutex is a semaphore (but a semaphore isn't necessarily a mutex). Like you may know, mutex stands for "MUTual EXclusion"; it's a semaphore but with only one "ressource". But as far as I know, pthread doesn't have a "couting semaphore" type (that's it, a true semaphore type -- but I might be wrong).

    In your situation, a binary semaphore (a mutex) is enough, there's no need to use a counting semaphore. But yeah, if you were using semaphores instead of mutexes, you would just have to replace the "lock" by "wait" and the "unlock" by "signal". Note that the semaphores should be initialized to 0 (and than there would be no need to call "lock/wait" in main).

    Indeed, I believe it's possible to create some sort of "counting semaphore type" using mutexes.
    I hate real numbers.

  5. #5
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> Oh and by the way, when main return, every threads close automatically, so you don't have to worry.
    This is true in your code - which has a implicit return from main(). In cecil's code, main never returns.

    There are 2 ways to end the "application" (the main thread and *all* created threads):
    - return from main()
    - call exit()

    If you call pthread_exit() from main(), then only the main thread is terminated. Any remaining threads keep on running. And since you never return from pthread_exit(), then technically, you never return from main().

    >> Just trying to get an idea of what semaphores are all about.
    I just think of them as a mutex with a "resource count" associated with them. Then how you use that "count" is up to you.

  6. #6
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    A pthread also terminates when it's function returns (return NULL) or just ends. Then when all pthread terminate the control shifts back to the main thread (which eventually/hopefully terminates)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. overlapped I/O and multi threading
    By krishnampkkm in forum C++ Programming
    Replies: 2
    Last Post: 06-22-2009, 03:27 PM
  2. Multi Threading
    By beon in forum C Programming
    Replies: 5
    Last Post: 12-04-2006, 09:21 PM
  3. Replies: 6
    Last Post: 06-02-2006, 08:32 AM
  4. starting to learn multi threading
    By hanhao in forum C++ Programming
    Replies: 2
    Last Post: 06-09-2004, 01:44 PM