Reputation: 55
I'm using pthreads to solve a producer-consumer problem. Basicaly the producer reads a file to a buffer and the consumers (at least one, but not limited) take entries from the buffer and operate them one by one. This is the producer:
//...Local stuff...
if(file){
while(fgets(line, 256, file)){
pthread_mutex_lock(&buffer_mutex);
while(data->buffer->buffer_items == data->buffer->buffer_size){
pthread_cond_wait(&buffer_full_cv, &buffer_mutex);}
data->buffer->buffer_items);
reads++;
add_to_head(data->buffer, line);
pthread_cond_broadcast(&buffer_ready_cv);
pthread_mutex_unlock(&buffer_mutex);
}
pthread_mutex_lock(&buffer_mutex);
work = 0;
pthread_mutex_unlock(&buffer_mutex);
fclose(file);
}
And this is the consumer:
//...Local stuff...
while(1){
pthread_mutex_lock(&buffer_mutex);
while(data->buffer->buffer_items == 0){
if(work)
pthread_cond_wait(&buffer_ready_cv, &buffer_mutex);
else if(!work && !data->buffer->buffer_items)
pthread_exit(NULL);
}
remove_from_tail(data->buffer, string_to_check);
data->buffer->buffer_items);
pthread_cond_signal(&buffer_full_cv);
pthread_mutex_unlock(&buffer_mutex);
for(unsigned int i = 0; i < data->num_substrings; i++){
cur_occurrence = strstr(string_to_check, data->substrings[i]);
while(cur_occurrence != NULL){
pthread_mutex_lock(&buffer_mutex);
data->occurrences[i]++;
cur_occurrence++;
cur_occurrence = strstr(cur_occurrence, data->substrings[i]);
pthread_mutex_unlock(&buffer_mutex);
}
}
}
What seems to be happening is the file is completely read and there's still work to be done, but as the producer is not running anymore, the wait in the consumer never finishes.
PS.: I've also tried pthread_cond_signal instead of broadcast, but didn't work either.
Anyway, Is there something I'm missing here?
Upvotes: 1
Views: 404
Reputation: 33719
What seems to be happening is the file is completely read and there's still work to be done, but as the producer is not running anymore, the wait in the consumer never finishes.
Technically, this is not a deadlock. This is a common challenge with producer/consumer thread configurations. There are various ways to deal with this.
pthread_cancel
after joining all consumers, so that pthread_cond_wait
is aborted. This is tricky to get completely right, though, and cancellation is best avoided in general.Note that if you have multiple consumers, each one needs to broadcast the signal after it observed that the end-of-data state has been reached, so that the other consumers have a chance to observe it, too,
Upvotes: 1