1

hi there i'm working on POSIX threads and i have a work like

  • We have 5 threads which each of them will print 'a','b','c','d,'e' separately with using same function
  • Threads must be created in alphabetical order.
  • Each character must be printed 50 times on screen
  • 'a' can only printed after all 'c's are printed
  • 'b' can only printed after all 'd's are printed
  • 'c' can only printed after all 'd's are printed

so before i display my code i have to explain what i have done. first of all, i have 5 global variables (which are flags and all of them set to 1 initiallly ) and i assigned them to the value which pthread_create() function returns. and then in the main function i used if() conditions before i joined threads. but i guess i'm trying the wrong way. the issue is i coundnt handle with the process "before thread_a, thread_d must finish its work". i will appreciate if you can help and suggest some better ideas. and here is my code,

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

int counter = 0;

int flag_a = 1;
int flag_b = 1;
int flag_c = 1;
int flag_d = 1;
int flag_e = 1;

pthread_mutex_t mymutex=PTHREAD_MUTEX_INITIALIZER;

void* thread_function(void* str);
void print_char(char* ch);

int main(){

    pthread_t thread_a, thread_b, thread_c, thread_d, thread_e;

    char* a = "a";
    char* b = "b";
    char* c = "c";
    char* d = "d";
    char* e = "e";


    flag_a = pthread_create( &thread_a, NULL, thread_function, (void*) a );
    flag_b = pthread_create( &thread_b, NULL, thread_function, (void*) b );
    flag_c = pthread_create( &thread_c, NULL, thread_function, (void*) c );
    flag_d = pthread_create( &thread_d, NULL, thread_function, (void*) d );
    flag_e = pthread_create( &thread_e, NULL, thread_function, (void*) e );

    if(flag_c==0)
        pthread_join( thread_a, NULL );

    pthread_join( thread_b, NULL );

    if(flag_d==0)
        pthread_join( thread_c, NULL );

    if(flag_d==0)
        pthread_join( thread_d, NULL );

    pthread_join( thread_e, NULL );

    printf("\nCounter = %d\n", counter);

    return 0;
}

void* thread_function(void* str) {

    int i;
    char* msg = (char*) str;

        for(i=0; i<50; i++) {

            pthread_mutex_lock(&mymutex);
            counter++;  
            print_char(msg);
            pthread_mutex_unlock(&mymutex);

        }
    }

void print_char(char* ch){

    int i;

    for(i=0; i<1; i++) {
        printf("%s --> ", ch);
        fflush(stdout);
        sleep(1);
    }
}

edit: i found a solution which prints the characters properly but the issue i cant print them asynchronousnly. i mean whenever i run the code it has same output like:

e-->d-->c-->b-->a (every character printed at 50 times )

and this the editted part of thread_function()

void* thread_function(void* str) {

    int i;
    char* msg = (char*) str;

        while( (strcmp(msg,"a") == 0) && (counter_c < 5) ){
        ;;
    }

        while( (strcmp(msg,"c") == 0) && (counter_d < 5) ){
        ;;
    }

        while( (strcmp(msg,"b") == 0) && (counter_d < 5) ){
        ;;
    }

        for(i=0; i<5; i++) {

            pthread_mutex_lock(&mymutex);               
            counter++;

                if( strcmp(msg,"d") == 0 )
                    counter_d++;

                if( strcmp(msg,"c") == 0 )
                    counter_c++;

            print_char(msg);
            pthread_mutex_unlock(&mymutex);

        }
    }
quartaela
  • 2,579
  • 16
  • 63
  • 99
  • I don't know how to solve this problem, but what about reducing the problem to two characters only? Should be the same essentially – stefan Oct 06 '12 at 18:09
  • well logically we can try on at least 3 characters and just 'a' will be printed after all 'd' are printed. – quartaela Oct 06 '12 at 18:11
  • Is there are spelling error becaue *'c' can only printed after all* **'D'***s are printed* or is it *'c' can only printed after all ***'E'***s are printed* – tozka Oct 06 '12 at 19:05
  • nope there is not any spelling error. the idea is 'c' and 'b' can only printed after all 'd' characters are printed. so main idea is thread_c and thread_b should wait thread_d to finish its work.(which is printed 50 times) – quartaela Oct 06 '12 at 19:08

4 Answers4

1

Logically, you have a dependency graph, and you need a way for each thread to a) wait for some condition to happen before it can begin to print it's stuff, and b) signal that it has completed printing, so that other threads waiting can start. In pthreads, this can be done with condition variables. So what you could do, instead of passing a pointer to the character to print, pass a pointer to a struct containing the character to print, a condition variable (and associated mutex) to wait on before starting the printing, and another condition variable with associated mutex to signal when done. And then in the main thread, before creating the threads, you of course need to setup all these structs appropriately, and after creating the threads, the main threads should signal those condition variables which are at the end (or beginning, depending on how you look at it..) of the dependency chain(s) in order to get the whole process started.

For in introduction how to use condition variables, see e.g. https://computing.llnl.gov/tutorials/pthreads/#ConditionVariables

janneb
  • 36,249
  • 2
  • 81
  • 97
  • i have a question about using condition variables. Could we use pthread_cond_signal() and pthread_cond_wait() functions in just only one function. (cause all threads have to use same function) – quartaela Oct 06 '12 at 20:13
  • finally i managed to use condition variables succesfully and it works perfectly! thanks janneb. – quartaela Oct 07 '12 at 12:19
1

// First print d then b or c after c's completion it will print a.then main function will wait for

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

int counter = 0;

int flag_a = 1;
int flag_b = 1;
int flag_c = 1;
int flag_d = 1;
int flag_e = 1;

pthread_mutex_t mymutex=PTHREAD_MUTEX_INITIALIZER;

void* thread_function(void* str);
void print_char(char* ch);

int main(){

    pthread_t thread_a, thread_b, thread_c, thread_d, thread_e;

    char* a = "a";
    char* b = "b";
    char* c = "c";
    char* d = "d";
    char* e = "e";

    flag_d = pthread_create( &thread_d, NULL, thread_function, (void*) d );
        pthread_join( thread_d, NULL );
    flag_b = pthread_create( &thread_b, NULL, thread_function, (void*) b );
    flag_c = pthread_create( &thread_c, NULL, thread_function, (void*) c );

  pthread_join( thread_c, NULL );

    flag_a = pthread_create( &thread_a, NULL, thread_function, (void*) a );
    flag_e = pthread_create( &thread_e, NULL, thread_function, (void*) e );

    //if(flag_c==0)
     //   pthread_join( thread_a, NULL );

   // pthread_join( thread_b, NULL );

    //if(flag_d==0)
      //  pthread_join( thread_c, NULL );

//    if(flag_d==0)
  //      pthread_join( thread_d, NULL );

    //pthread_join( thread_e, NULL );

    printf("\nCounter = %d\n", counter);
pthread_exit(NULL);  //or you can join thread e before printf() statement 
    return 0;
}

void* thread_function(void* str) {

    int i;
    char* msg = (char*) str;

        for(i=0; i<50; i++) {

            pthread_mutex_lock(&mymutex);
            counter++;  
            print_char(msg);
            pthread_mutex_unlock(&mymutex);

        }
    }

void print_char(char* ch){

    int i;

    for(i=0; i<1; i++) {
        printf("%s --> ", ch);
        fflush(stdout);
  //      sleep(1);
    }
}
jayesh hathila
  • 279
  • 1
  • 6
  • 14
  • yes this will be a true option but as i said in "martin james" answer threads must created in alphabetical order and we should use only one function. – quartaela Oct 06 '12 at 20:29
  • 1
    It can be done by signal handler..First on thread creation some function ISR() will be called(in this function ordering of calling a function named thread_function(void* str) will be called) for every thread, it will keep thread let say thread_a and thread_b on waiting mode until thread_d sends some signal(by kill signal) which states that thread_d has completed its work and so on for other threads. – jayesh hathila Oct 06 '12 at 22:23
0

Actually what you want is to suspend threads before starting to work, and until a given thread had finished.

  • Thread A: prints A's
  • Thread B: prints B's
  • Thread C: prints C's
  • Thread D: prints D's

In your case, you want A to wait for C, B and C to wait for D and launch D. For this you need semaphores, since a semaphore will block the thread until it is noticed to wake up.

Community
  • 1
  • 1
m0skit0
  • 25,268
  • 11
  • 79
  • 127
0

Maybe I misunderstand the requirement? Pseudo:

Start Ethread('e'); // can run async, since no contraints on 'e'
Start Dthread('d'); // print 'd' and 
Join Dthread;       // wait for 'd' to finish
Start Bthread('b'); // now start on the 'b'
Start Cthread('c'); // and the 'c'
Join Cthread;       // but just wait for the 'c' to finish
Start Athread('a'); // and then print the 'a'

Each thread prints its passed char 50 times. If the common output routine needs a mutex, OK.

Does that not satisfy the requirement?

Martin James
  • 24,453
  • 3
  • 36
  • 60
  • i forgot to mention that threads must be created in the alphabetical order. like first create a-->b-->c and goes on. i guess i should use condition variable as "janneb" told as an answer. – quartaela Oct 06 '12 at 19:56