title: Reader/Writer problem in C using pthreads
body: <p>I am learning pthreads when I came across the reader/writer problem in C. The problem is very simple where the "writer" threads will be accessing data from an external source and the "reader" threads will be reading this data from the shared buffer and then pseudo processing the data. The reader and writer threads need to run continuously in a while loop.</p>
  
  <p>I am trying to implement and compile this on a standard unix system with a POSIX interface. </p>
  
  <p>I have looked through some of the stack overflow questions:</p>
  
  <p><a href="https://stackoverflow.com/questions/23094813/reader-writer-program-in-c-using-mutexes-and-pthreads">Reader Writer program in C using mutexes and pthreads</a></p>
  
  <p><a href="https://stackoverflow.com/questions/19482648/reader-writer-lock-in-pthread">reader/writer lock in pthread</a></p>
  
  <p>and I have gotten no where with these.</p>
  
  <p>Here is what I have so far:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;string.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;pthread.h&gt;
  #include &lt;semaphore.h&gt;
  #include &lt;assert.h&gt;
  
  #define BUFF_SIZE 50
  #define M 10
  #define N 20
  
  int get_external_data(char *buffer, int bufferSizeInBytes);
  void process_data(char *buffer, int bufferSizeInBytes);
  
  int get_external_data(char *buffer, int bufferSizeInBytes){
      int status;
      int val;
      char srcString[] = "0123456789abcdefghijklmnopqrstuvwxyxABCDEFGHIJKLMNOPQRSTUVWXYZ";
  
      val = (int)(rand() % 62);
      if (bufferSizeInBytes &lt; val){
          return (-1);
      }
  
      strncpy(buffer, srcString, val);
      return val;
  }
  
  void process_data(char *buffer, int bufferSizeInBytes){
      int i;
      if(buffer) {
          printf("thread %li - ", pthread_self());
  
          for(i = 0; i &lt; bufferSizeInBytes; i++) {
              printf("%c", buffer[i]);
          }
  
          printf("\n");
          memset(buffer, 0, bufferSizeInBytes);
      } else {
          printf("error in process data - %li\n", pthread_self());
      }
  
      return;
  }
  
  
  pthread_mutex_t data_lock = PTHREAD_MUTEX_INITIALIZER;
  pthread_mutex_t print_lock = PTHREAD_MUTEX_INITIALIZER;
  sem_t data_count;
  
  typedef struct node {
      struct node *next;
      char *data;
      int length;
  } node_t;
  
  node_t *head, *tail;
  
  /**
   * This thread is responsible for pulling data off of the shared data 
   * area and processing it using the process_data() API.
   */
  
  void *reader_thread(void *arg) {
      int rc;
      node_t *removed_node;
  
      while(1) {
          rc = sem_wait(&amp;data_count);
          if (0 != rc) {
              return NULL;
          }
  
          pthread_mutex_lock(&amp;data_lock);
  
          assert(NULL != head);
          removed_node = head;
          head = head-&gt;next;
  
          pthread_mutex_unlock(&amp;data_lock);
  
          //Adding this lock for sake of readability at the cost of reduced consumption rate...will run out of memory eventually.
  
          pthread_mutex_lock(&amp;print_lock);
  
          process_data(removed_node-&gt;data, removed_node-&gt;length);
  
          pthread_mutex_unlock(&amp;print_lock);
  
          free(removed_node-&gt;data);
          free(removed_node);
      }
  
      return NULL;
  }
  
  
  /**
   * This thread is responsible for pulling data from a device using
   * the get_external_data() API and placing it into a shared area
   * for later processing by one of the reader threads.
   */
  
  void *writer_thread(void *arg) {
      int length;
      char *buffer;
      node_t *new_node;
  
      new_node = (node_t*) malloc(sizeof(*new_node));
      buffer = (char*) malloc(sizeof(*buffer) * BUFF_SIZE);
  
      while(1) {
  
          length = get_external_data(buffer, BUFF_SIZE);
  
          if (length == -1) {
              //data too big, discard it and try again;
              continue;
          }
  
          new_node-&gt;next = NULL;
          new_node-&gt;length = length;
          new_node-&gt;data = buffer;
  
          pthread_mutex_lock(&amp;data_lock);
  
  
          if (head == NULL) { //The linked list is completely empty   
              head = new_node;
              tail = new_node;        
          } else { //There are items in the list and we're appending  
              tail-&gt;next = new_node;
              tail = new_node;
          }
  
          pthread_mutex_unlock(&amp;data_lock);
  
          pthread_mutex_lock(&amp;print_lock);
  
          printf("thread %ld wrote - %s \n", pthread_self(), buffer);
  
          pthread_mutex_unlock(&amp;print_lock);
  
          sem_post(&amp;data_count);
  
          buffer = (char*) malloc(sizeof(*buffer) * BUFF_SIZE);
          new_node = (node_t*) malloc(sizeof(*new_node));
      }
  
      return NULL;
  }
  
  int main(int argc, char **argv) {
      int i = sem_init(&amp;data_count, 0, 0);
      pthread_t dummy; //creating a dummy thread
  
      for(i = 0; i &lt; N; i++) { 
          pthread_create(&amp;dummy, NULL, reader_thread, NULL);
      }
  
      for(i = 0; i &lt; M; i++) { 
          pthread_create(&amp;dummy, NULL, writer_thread, NULL);
      }
  
      sleep(100);
      return 0;   
  }
  </code></pre>
  
  <p>The thread synchronization is there without any compilation errors but my program stops after the writer thread writes on a buffer a few times.</p>
  
  <p>The reader and writer threads need to run continuously in a while loop, but they don’t in my case. </p>
  
  <p>Any idea on how to resolve this issue?</p>