Reputation: 575
I have a worker thread processing a queue of work items.
//producer
void push_into_queue(char *item) {
pthread_mutex_lock (&queueMutex);
if(workQueue.full) { // full }
else{
add_item_into_queue(item);
pthread_cond_signal (&queueSignalPush);
}
pthread_mutex_unlock(&queueMutex);
}
// consumer1
void* worker(void* arg) {
while(true) {
pthread_mutex_lock(&queueMutex);
while(workQueue.empty)
pthread_cond_wait(&queueSignalPush, &queueMutex);
item = workQueue.front; // pop from queue
add_item_into_list(item);
// do I need another signal here for thread2?
pthread_cond_signal(&queueSignalPop);
pthread_mutex_unlock(&queueMutex);
}
return NULL;
}
pthread_create (&thread1, NULL, (void *) &worker, NULL);
Now I would like to have thread2
consume the data inserted in add_item_into_list()
but only if items have been added to the list. Note that the list is permanent and can't be emptied nor freed for the entire duration of the program.
So my question is: do I need another pthread_cond_signal
?, if yes, where would this signal go? and how my other worker would look like (canonical form)?
Upvotes: 1
Views: 322
Reputation: 9706
I see 2 possible ways of solving the problem:
a. Introduce another condition variable (e.g. signalList
) for the list, so that consumer2
thread would wait for events on it. In this case consumer1
have to signal twice: once on queueSignalPop
and once on signalList
:
// consumer1
void* worker(void* arg) {
while(true) {
// ...
pthread_cond_signal(&queueSignalPop);
pthread_cond_signal(&signalList);
pthread_mutex_unlock(&queueMutex);
}
return NULL;
}
b. Use existing condition queueSignalPop
variable inside consumer2
to wait for events, and use broadcast instead of signal inside consumer1
. Broadcast means all the waiting threads on condition variable will wake up:
// consumer1
void* worker(void* arg) {
while(true) {
// ...
pthread_cond_broadcast(&queueSignalPop);
pthread_mutex_unlock(&queueMutex);
}
return NULL;
}
// consumer2
void* worker2(void* arg) {
while(true) {
while(list.empty)
pthread_cond_wait(&queueSignalPop, &queueMutex);
// ...
}
return NULL;
}
I would propose to go for the first approach, since it better distinguish the purpose of each condition variable.
Upvotes: 1