Producer-consumer code The idea I have in my head is this:



I am not sure if I need the index variable in consumer and producer.

Moreover, I want to know if it is OK like this (it seems to work), or it is just some stupid working code. Can it be more clever/efficient? Leave the readability for me.

My code will use the POSIX semaphore mutex in order to access the CS (which is writing/reading from the shared buffer of words).

full and empty are there to indicate if the buffer is full, or empty, so that we don't write a word if the buffer is full (we will overwrite the first word if we do that, before consumer reads it). Similarly, we don't want to read from any empty buffer!

When the producer is done, it sets a shared flag (initialized in 0). However, in the consumer side I had to check not only for the flag but for the values of full and empty.

The size of the buffer is 15. n (and the typo m) in the picture below is in our case 15.

Producer:

int index = 0;
size_t str_len;
while (fgets(buf, sizeof(buf), fp) != NULL) {
  str_len = strlen(buf);
  if(buf[str_len - 1] != '\n')
    printf("Didn't read whole line!\n");
  else {
    buf[str_len - 1] = '\0';
    sem_wait(&amp;(sh-&gt;empty));
    sem_wait(&amp;(sh-&gt;mutex));
    printf("|%s|\n", buf);
    strcpy(sh-&gt;words[index], buf);
    index = (index + 1) % N;
    sem_post(&amp;(sh-&gt;mutex));
    sem_post(&amp;(sh-&gt;full));
  }
}
sem_wait(&amp;(sh-&gt;mutex));
sh-&gt;done = 1;
sem_post(&amp;(sh-&gt;mutex));
int full_val;
sem_getvalue(&amp;(sh-&gt;full), &amp;full_val);
while(full_val++ &lt;= 0) { // 'if' instead of 'while' should be OK too
  sem_post(&amp;(sh-&gt;full));
}


Consumer:

int index = 0;
while(1) {
  sem_wait(&amp;(sh-&gt;full));
  sem_wait(&amp;(sh-&gt;mutex));
  int full_val, empty_val;
  sem_getvalue(&amp;(sh-&gt;full), &amp;full_val);
  sem_getvalue(&amp;(sh-&gt;empty), &amp;empty_val);
  if(empty_val != 15)
    printf("got: %s\n", sh-&gt;words[index]);
  if(sh-&gt;done == 1 &amp;&amp; full_val == 0)
    break;
  index = (index + 1) % N;
  sem_post(&amp;(sh-&gt;mutex));
  sem_post(&amp;(sh-&gt;empty));
}


I am obliged to use sem_wait() and sem_post() by the way.



After the answers, I think that the main question is that if I can avoid the extra post in full semaphore after the while of producer is ended. 

The problem if I remove the posting of full is in the following case:


Producer puts all the words in the buffer.
Scheduler gives the CPU to consumer.
Consumer reads all the words and gets suspended because on the full
semaphore.
Now, scheduler gives the CPU to producer which now sets the shared
flag to 1.
Scheduler goes back to consumer, which is suspended on full
semaphore, forever.
Robust code does not assume the first char in buf is not '\0'.

This is a pedantic point, but user IO is a hacker paradise - best to code defensively.

Instead of:

size_t str_len;
while (fgets(buf, sizeof(buf), fp) != NULL) {
  str_len = strlen(buf);
  if(buf[str_len - 1] != '\n')
    printf("Didn't read whole line!\n");
  else {
    buf[str_len - 1] = '\0';


use to prevent undefined behavior (UB) with buf[str_len - 1].

while (fgets(buf, sizeof(buf), fp) != NULL) {
  size_t str_len = strlen(buf);
  if (str_len == 0 || buf[str_len - 1] != '\n') {
    printf("Didn't read whole line or embedded null character detected!\n");
  } else {
    buf[str_len - 1] = '\0';