Originally Posted by
brewbuck
The problem is the controller itself, which should not exist. The threads should increment the value of the variable themselves, then signal the condvar. Each thread, upon waking from the cond_wait(), will find a fresh value in the variable.
This method will not work if the "incrementing variable" is anything but a counter: eg, if the control thread is producing non-contiguous unique values for consumption by the other threads, then a separate controller must exist.
The problem is making the producer/controller wait while the consumer/workers work. To do this you need one global condition and one global mutex; the producer needs the lock at each iteration of it's task, but only the consumers can unlock it. The consumers all wait on the same condition, which is signalled once each time by the producer -- then one consumer consumes and unlocks the lock so the producer can continue:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_cond_t Cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t Lock = PTHREAD_MUTEX_INITIALIZER;
int X;
void *consumer(void *id) {
pthread_mutex_t local = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&local);
while (1) {
pthread_cond_wait(&Cond,&local);
copy = X; /* get the variable */
pthread_mutex_unlock(&Lock);
printf("%p: %d\n",id,copy);
}
}
void *producer() {
int i;
for (i=0;i<100;i++) {
printf("%d ",i);
pthread_mutex_lock(&Lock);
X = rand();
pthread_cond_signal(&Cond);
}
return NULL;
}
int main() {
pthread_t p,a,b;
setvbuf(stdout,NULL,_IONBF,0);
pthread_create(&a,NULL,consumer,(void*)0xA);
pthread_create(&b,NULL,consumer,(void*)0xB);
/* maybe: sleep(1) */
pthread_create(&p,NULL,producer,NULL);
pthread_join(p,NULL);
return 0;
}
You can actually replace the mutex with a boolean flag set by the producer and unset by the consumer; the producer waits with a while(Flag) -- but this is active whereas the mutex is passive.