Reputation: 195
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.
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
Upvotes: 2
Views: 578
Reputation: 11007
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]);
}
}
Upvotes: 2