2

I have a question about C threads and their return value. My goal is to find all the prime numbers between a beginning number and an ending number. I will have 4 threads, and each thread does a quarter of the range.

So for example, the primes between 1 and 100.

  • thread 1 finds the primes between 1 - 25
  • thread 2 26 - 50
  • thread 3 51 - 75
  • thread 4 76 - 100

All the prime numbers will be stored in an array and there will be a function that computes the primes.

My question is, when I join the threads

pthread_join(tids[i], ptr);

will ptr be a pointer to a combined array of ALL primes, 1 - 100?

Meaning if I use a for loop to print the values

printf("%d", ptr[i]); 

will it print all the primes from 1 - 100 as one big array?

Am I joining the 4 separate arrays?

Thank you

pmod
  • 10,450
  • 1
  • 37
  • 50
user2817240
  • 195
  • 1
  • 5
  • 13

1 Answers1

2

phtread_join() will return through ptr what corresponding thread passes to pthread_exit(). Each thread is working independently and computes own set of primes, so, each thread should create own array and after all threads are joined you will print results of each array. To be able to return result set of primes and its count, we have to use own struct type:

struct comp_result {
     unsigned *p_arr;
     unsigned count;
};

I will illustrate the way Without locking:

compute_thread (...) {
    ...
    struct comp_result *p_res = malloc(sizeof(struct comp_result));        
    p_res->p_arr = NULL;
    p_res->count = 0;
    for (num = start; num < end; num++) {
         if (is_prime(num)) { 
              p_res->count++; /// increment number of primes and expand our storage
              p_res->p_arr = realloc(p_res->p_arr, p_res->count*sizeof(int));
              p_res->p_arr[p_res->count-1] = num; // save prime in result array
         }
    }  

    // pass pointer to per-thread result data
    pthread_exit(p_res);
}


 main () {
      .... // create threads
      ....
      for (i = 0; i < num_of_threads; i++) {
           struct comp_result *p_res;
           // retrieve and print array from i-thread
           pthread_join(tids[i], &p_res);
           for (num = 0; num < p_res->count; num++) {
                printf(" %d ", p_res->p_arr[num]);
           }
           free(p_res->p_arr);
           free(p_res);
      }
 } 

The illustration with locking needs one more struct type since we will pass pointer to result shared data into each thread:

struct control {
    unsigned start;
    unsigned end;
    struct comp_result *p_res;
}

compute_thread (ptr) {
    struct control *p_cont = (struct control*)ptr;
    // retrieve the pointer to shared, but be accurate with it!
    struct comp_result *p_res = p_cont->p_res;

    // initialize lock
    pthread_mutex_init(&p_res->lock, NULL);

    ...
    for (num = p_cont->start; num < p_cont->end; num++) {
         if (is_prime(num)) {
              pthread_mutex_lock(&p_control->lock);
              // modify shared data with locking 
              p_res->count++; /// increment number of primes and expand our storage
              p_res->p_arr = realloc(p_res->p_arr, p_res->count*sizeof(int));
              p_res->p_arr[p_res->count-1] = num; // save prime in result array
              pthread_mutex_unlock(&p_control->lock);
         }
    }  

    pthread_exit(NULL);
}


 main () {
      //create one shared data and initialize it:
      struct comp_result *p_res = malloc(sizeof(struct comp_result));        

      p_res->p_arr = NULL;
      p_res->count = 0;

      for (i = 0; i < num_of_threads; i++) {
            // create per-thread control data:
            struct control *p_control = malloc(sizeof(struct control));        
            p_control->start = 
            p_control->end =
            p_control->p_res = p_res;
            pthread_crate(&tids[i], NULL, compute_thread, p_control);
      }
      ....
      for (i = 0; i < num_of_threads; i+++) {
           pthread_join(tids[i], NULL);
      }
      // now all threads are completed and we are ready to read result:
      for (num = 0; num < p_res->count; num++) {
           printf(" %d ", p_res->p_arr[num]);
      }
 } 
pmod
  • 10,450
  • 1
  • 37
  • 50
  • Alright thanks. And also could I declare a void *ptr = NULL; and then in my join function do pthread_join(tids[i], &ptr); Would that work? – user2817240 Dec 08 '13 at 01:39
  • So in this case, ptr is a variable that points to an array. So then I can use a for loop, cast the pointer into my structure type, and print the primes in the array? – user2817240 Dec 08 '13 at 01:41
  • So since I will have 4 arrays, could I use the ptr variable and make one array and return that? – user2817240 Dec 08 '13 at 01:41
  • @user2817240 yes, you can use void *ptr and pass it as you wrote, and then cast, but technically this is the same. Yes, you if you have 4 threads - you have 4 arrays and you can create one more joined array and copy from 4 into this joined array. There are other options as well to use one joined array all the way, but that needs locking, i.e. using mutexes for example. – pmod Dec 08 '13 at 11:23