im trying to implement a multi threading with multible threads (user can enter number of workers = threads when starting the programm) where each thread calling functionA and afterwards functionB. But before functionB should only be executed after ALL threads have called functionA. Thats my pseudo code:
void* worker_do(void* worker_id)
{
functionA((size_t) worker_id);
// First thread should only start functionB after ALL threads
// are finished with functionA
functionB((size_t) worker_id);
return NULL;
}
// I am not allowed to change pthread_create and pthread_join here
int main()
{
// should be a flexible value
ssize_t num_workers = 20;
pthread_t* workers = malloc(num_workers*sizeof(pthread_t));
for(ssize_t i = 0; i < num_workers; i++)
pthread_create(&workers[i], NULL, worker_do, (void*) i);
for(ssize_t i = 0; i < num_workers; i++)
pthread_join(workers[i], NULL);
free(workers);
return 0;
}
I googled and found the possiblity of "condition variables". But I am not sure show they have to implemented for the condition
IF last_thread_has_called_functionA THEN start_calling_fuctionB
Or are condition variables not the right instrument to solve this issue?
Would really appreciate tipps how i can implement that...
bw Robert
Since you asked, to do this with a condition-variable and mutex, you could so something like this:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <inttypes.h>
#define N_THREADS 10
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
unsigned int count = 0;
void functionA(intptr_t id)
{
printf("functionA: %" PRIdPTR "\n", id);
}
void functionB(intptr_t id)
{
printf("functionB: %" PRIdPTR "\n", id);
}
void* thread_proc(void* pv)
{
intptr_t id = (intptr_t)pv;
functionA(id);
// lock the mutex to protect the predicate data (count)
pthread_mutex_lock(&mtx);
++count;
pthread_cond_broadcast(&cv);
// wait for all threads to finish A
while (count < N_THREADS)
pthread_cond_wait(&cv, &mtx);
// this is still owned by us. release it.
pthread_mutex_unlock(&mtx);
// now B
functionB(id);
return NULL;
}
int main()
{
pthread_t thrds[N_THREADS];
for (int i=0; i<N_THREADS; ++i)
pthread_create(thrds+i, NULL, thread_proc, (void*)(intptr_t)(i+1));
for (int i=0; i<N_THREADS; ++i)
pthread_join(thrds[i], NULL);
return EXIT_SUCCESS;
}
Sample Output (varies)
functionA: 1
functionA: 4
functionA: 6
functionA: 3
functionA: 2
functionA: 8
functionA: 9
functionA: 7
functionA: 10
functionA: 5
functionB: 10
functionB: 9
functionB: 5
functionB: 7
functionB: 4
functionB: 6
functionB: 1
functionB: 2
functionB: 8
functionB: 3
That said, as Jonathan pointed out in general comment, a barrier is a more elegant solution to this issue. I would post an example, but alas my environment doesn't support them (sad, mac os x). They're available on most Unix pthread implementations, so if your target platform provides them, I suggest investigating them proper.