I am implementing a consumer-producer problem with using pthreads in ubuntu 16.04 on a virtual machine with 2 processers. We have n number of producers and a single consumer that reads data from each producer through buffers. Each producer has its own buffer. The problem is that at some point my code deadlocks and could not find out why. May be i am messing up with the condition variables and mutex locks.
typedef struct
{
Student* buf; // the buffer
int producer_id;
size_t len; // number of items in the buffer
pthread_mutex_t mutex; // needed to add/remove data from the buffer
pthread_cond_t can_produce; // signaled when items are removed
pthread_cond_t can_consume; // signaled when items are added
bool isDone;
} buffer_t;
This the buffer struct for the data transfer between consumer and producers.
void* producer(void *param)
{
buffer_t* buffer = (buffer_t*)param;
char* line = NULL;
size_t len = 0;
ssize_t read;
FILE* inFileReader;
inFileReader = fopen(inFile, "r");
while ((read = getline(&line, &len, inFileReader)) != -1)
{
pthread_mutex_lock(&buffer->mutex);
if (buffer->len == BUFFER_SIZE)
{// buffer full wait
pthread_cond_wait(&buffer->can_produce, &buffer->mutex);
}
//buffer filled up with the read data from the file.
if (conditionValid)
{
//add item to buffer
++buffer->len;
}
pthread_cond_signal(&buffer->can_consume);
pthread_mutex_unlock(&buffer->mutex);
}
fclose(inFileReader);
buffer->isDone = true;
pthread_exit(NULL);
return NULL;
}
This is the producer, reads data from a file given and fills up the buffer and when the file ends the producer thread will exit.
void* consumer(void *param)
{
buffer_t* buffer_array = (buffer_t*)param;
sleep(rand() % 3);
int i =0;
while (!buffer_array[i%N].isDone || buffer_array[i%N].len != 0)
{
pthread_mutex_lock(&buffer_array[i%N].mutex);
if (buffer_array[i%N].len == 0)
{
pthread_cond_wait(&buffer_array[i%N].can_consume,
&buffer_array[i%N].mutex);
}
while (buffer_array[i%N].len != 0)
{
buffer_array[i%N].len--;
//read from buffer
}
pthread_cond_signal(&buffer_array[i%N].can_produce);
pthread_mutex_unlock(&buffer_array[i%N].mutex);
i++;
}
fclose(outFileWriter);
pthread_exit(NULL);
return NULL;
}
The consumer reads buffers from each producer and when all done consumer exit the loop and terminates the thread.
Any help appreciated.
pthread_cond_wait
. At the risk of souinding grossly self-serving, see this answer for some advice, caveats, and potential pitfalls of pthreads with mutex+cvar usage. – WhozCraigif (!cond) { pthread_cond_wait }
. Alwayswhile (!cond) { pthread_cond_wait }
. – ikegamii%N
all over the place, you can replacei++;
andi%N
with with i = (i+1) % N;` andi
. – ikegami