Here is my consumer code, i removed the computation part since it's (i think) irrelevant :
void *compute()
{
struct document** document;
document = (struct document**)malloc( sizeof(struct document*) );
while( ( hasNextData || counter > 0 ) ) {
sem_wait( &full );
pthread_mutex_lock( &buffer_access) ;
if( remove_document( document ) ) {
fprintf( stderr, "Consumer report error condition\n");
pthread_mutex_unlock(&buffer_access);
}
else {
// pthread_mutex_unlock( &buffer_access );
// Compute the document
}
sem_post( &empty );
}
free( document );
pthread_exit( 0 );
}
I also have a producer which will produce documents
and put them in a buffer. If the buffer is full, it waits for the documents to be processed (they are removed by remove_document
). When the input file is entirely read, it stops and the thread exits.
This code works well with one consumer thread or two, but when there are more, it deadlocks. I think the problem is with the waiting semaphore.
Let's pretend we have 6 input lines (they will create documents in the buffer) and 10 consumer threads. Ten threads will be created to process only 6 inputs. So at best there will be 4 locking threads if each thread processes one data ? And at worst 9 locking threads ?
That's my understanding of the problem. But I don't know how to prevent that since the tutorials I read were using while(1) as a condition in both the producers and the consumers.
Is there a standard/common way to solve the consumer-producer problem when they don't produce/consume while(true) ?
Or should i tweak with counters ? But i don't see where to put the condition. If i put it outside the wile, i'll just kill threads before they work on something, if i put it inside they will be locked by the sem_wait()
EINTR
which the code should check for. If it is not atsem_wait
it will just continue executing. The signal handler should set a flag to say that the thread should stop processing and thewhile
loop should be checking this flag. – kaylum