Reputation: 13
I'm writing a toy program to help me understand how barriers work. In the program I have each thread checking to see if an element in one array is in another array. I was able to have all threads start searching simultaneously but I'd like to have them all meet up after filtering in order to correctly add any numbers to the array.
Without doing so, the the wrong numbers might be added to the array.
EDIT: Someone suggested I'd add pthread_barrier_wait(&after_filtering); in the call to filter_threads and that seemed to do trick. Now I know that I have to add a wait call in main as well as in the filter function, but I don't quite understand the flow of execution and how the wait calls in main work. I know that the wait in the thread function ensures that all threads reach that point before continuing but doesn't that happen as soon as the threads created? Meaning that nums should have values of 99 instead of 4, 3, 8, 1?
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
pthread_barrier_t before_filtering, after_filtering;
int nums[4] = {99, 99, 99, 99};
int arr[15] = {12, 5, 31, 8, 1, 6, 24, 4, 81, 42};
void filter(int i, int a[]){
// Loop through the list
int j;
for (j = 0; j < 10; j++)
{
if (nums[i] == a[j])
nums[i] = 0;
}
}
void *filter_threads(void *id){
int *myid = (int *)id;
printf("thread %d\n",*myid);
pthread_barrier_wait(&before_filtering);
filter(*myid, arr);
pthread_barrier_wait(&after_filtering);
}
int main(void)
{
pthread_t tids[3];
int index[3];
pthread_barrier_init(&before_filtering, NULL, 4);
pthread_barrier_init(&after_filtering, NULL, 4);
int i, j;
for (i = 0; i < 3; i++)
{
index[i] = i + 1;
pthread_create(&tids[i], NULL, filter_threads, &index[i]);
}
// Cannot call any filter function without first populating nums
nums[0] = 4;
nums[1] = 3;
nums[2] = 8;
nums[3] = 1;
pthread_barrier_wait(&before_filtering);
filter(0, arr);
pthread_barrier_wait(&after_filtering);
// Add new numbers to arr...
printf("New nums: ");
for (i = 0; i < 4; i++)
printf("%d, ", nums[i]);
printf("\n");
for (i = 0; i < 3; i++)
pthread_join(tids[i], NULL);
// Print new arr...
pthread_barrier_destroy(&before_filtering);
pthread_barrier_destroy(&after_filtering);
}
I tried adding another wait call after the filtering but now the program just hangs. How can I accomplish this?
Upvotes: 0
Views: 1507
Reputation: 12337
A barrier is simply a mechanism to ensure that all N threads reach a certain point in the code before continuing. Hence, if you call pthread_barrier_init
with a count of 4, any thread calling pthread_barrier_wait
on that same barrier will not continue until three other threads have also called pthread_barrier_wait
.
So, as your code provides now: the three created threads will, once started, execute the pthread_barrier_wait(&before_filtering)
where they will all block until after the main thread has executed sleep(3)
and then initialized the nums
array. The main thread then calls pthread_barrier_wait(&before_filtering)
. This releases the main thread and all the others to continue execution.
After executing the filter
function, each sub-thread and the main thread should execute pthread_barrier_wait(&after_filtering)
. Otherwise, the main thread will be stalled waiting for three other threads to wait on the barrier.
That being said, there is no need to use the second barrier at all. At that point, the main thread is really just waiting for the other three threads to finish their task and quit. The pthread_join
on each sub-thread being done by the main thread accomplishes the same thing: i.e. the pthread_join
on a thread will not return until that thread has finish execution.
Upvotes: 1